find:名前に数字を含むディレクトリと、サブディレクトリを除くすべてのディレクトリを一覧表示します。

find:名前に数字を含むディレクトリと、サブディレクトリを除くすべてのディレクトリを一覧表示します。

数字のないすべてのディレクトリ(元のパスを除く)を見つけるには、次のコマンドを実行します。

find /path/2/directory -type d -name '[!0-9]*'

問題は、見つかったディレクトリがその番号のディレクトリのサブディレクトリであることです。

例:

/path/2/directory/20160303/backup

でも

/path/2/directory/backup20160303a/backup

findがそのようなディレクトリを返すのを防ぐ方法はありますか?

深さを制限するだけでは、この問題を解決できません。深さはさまざまです。

例:

/path/2/directory/subdirectory/20160303/backup

答え1

-prune次のディレクトリを無視するために使用されます。

find /path/to/directory -name '*[0-9]*' -prune -o -type d -print

ただしgnu、これを設定する場合は、上記のCコマンドを実行するときにロケールを使用することをお勧めします。以下のStéphaneの説明を参照してください。

答え2

find が特定の一致を超えないようにするには、たとえば with の出力をフィルタリングする-prune代わりに and を使用する必要があります。-pathfindgrep -v

findテスト用に不要な資料が表示されないことを確認できるように、追加のファイルとサブディレクトリを含む環境を作成します。

mkdir -p tmp/2/abc/def
touch tmp/2/abc/def/file1
mkdir -p tmp/2/abc/9876/xyz
touch tmp/2/abc/9876/xyz/file2
tree tmp/

以下を提供します。

tmp
└── 2
    └── abc
        ├── 9876
        │   └── xyz
        │       └── file2
        └── def
            └── file1

find tmp/2/abc \! -path "*[0-9]*"@terdonの提案によれば、以下から始まるディレクトリだけでなくフルパスも考慮されるため、出力は空になり-pathます。abc2

@casが提案したようにこれを行うと、find tmp/2/abc -type d | grep -vE '/[0-9-]+(/|$)'検索しているファイルとのみ一致するのではなく、名前付きディレクトリと一致するため、何も印刷されないことがわかります2。まず最初にツリー全体を巡回するには find が必要で9876、そこに数十万の項目がある場合、巡回 (およびフィルタリング) に多くの時間がかかります。

これにより:

find tmp/2/abc -type d -name '[!0-9]*' -print 

出力にパスが含まれていることがわかりますtmp/2/abc/9876/xyz。それを取り除くには、望ましくないものを切り取ります-prune

find tmp/2/abc -type d -name '[!0-9]*' -print -o -name '[0-9]*' -prune

これは作る:

tmp/2/abc
tmp/2/abc/def

@don_cristtiがこの回答を向上させるために行ったトリムと印刷を置き換えることで、効率をわずかに向上させることができます。

答え3

私はあなたが探していると思います-path

   -path pattern
          File  name matches shell pattern pattern.  The metacharacters do
          not treat `/' or `.' specially; so, for example,
                    find . -path "./sr*sc"
          will print an entry for a directory called `./src/misc' (if  one
          exists).  

指定されたパターンに対して各ファイル/ディレクトリのフルパスを取得します。したがって、次のディレクトリ構造がある場合:

$ tree
.
├── 111
│   └── foo
│       └── bar
├── bar
│   └── foo
│       └── baz
└── foo
    └── 111
        └── bar

9 directories, 0 files

次のように使用できますfind

$ find /path/to/directory/ \! -path "*[0-9]*" 
.
./foo
./bar
./bar/foo
./bar/foo/baz

またはGNUを使用してくださいfind

find /path/to/directory/ -not -path "*[0-9]*" 

これは、名前を解決するために各ディレクトリをドリルダウンする必要があるため、大きなディレクトリツリーよりも大きなディレクトリツリーではるかに遅いです。@Anthonのソリューションプラムと一緒に。しかし、何千ものディレクトリがなくても大丈夫です。

答え4

grep(またはまたはなど)を使用して、awk出力sedからperlこれらのディレクトリを簡単に削除できます。find

find /path/to/directory -type d | grep -vE '/[0-9-]+(/|$)'

-注:日付を含むディレクトリは時々YYYYMMDDではなくYYYY-MM-DDであるため、これを文字クラスに含めました。

関連情報