GNU find は親ディレクトリを含む

GNU find は親ディレクトリを含む

GNU find に、指定されたファイル名までのエントリを除外するようにしています。

次のサンプルツリーを見てみましょう。

./foo
./foo/another.txt
./foo/bar
./foo/bar/world
./foo/bar/world/test.txt
./foo/bar/world/hello.txt

( や他のディレクトリにも多数のファイルが存在するためworld、単に を検索するわけではありませんhello.txt)。

'test.txt' とその親ディレクトリ以外のすべてに一致させたいです。

出力は単純に になりますfoo/bar/world/hello.txt

このコマンドは正しい結果を生成しますが、かなり乱雑であり、同じ名前のディレクトリが複数ある場合は間違った結果を生成します。

find * ! -name test.txt -a ! -name foo -a ! -name bar -a ! -name world

答え1

findディレクトリではなく、ファイルのみに関心があることを伝えます。

find ./foo -type f ! -name test.txt

アップデート:

次のような少し複雑な例があるとします。

$ find ./foo
./foo
./foo/baz
./foo/baz/b.csv
./foo/baz/a.txt
./foo/bar
./foo/bar/c.txt
./foo/bar/world
./foo/bar/world/hello.txt
./foo/bar/world/test.txt

何かを削除することが目的の場合は、-depthディレクトリの前にファイルが表示されるように指定する必要があります。

$ find ./foo -depth
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo

保持したいパスがわかっている場合は、その一部に一致する正規表現を作成できます。

$ find ./foo -depth -regextype posix-extended -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo

次に、正規表現を否定して、削除したいものを取得します。

$ find ./foo -depth -regextype posix-extended ! -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt

答え2

ツリーの正確な深さがわかっている場合 (つまり、3 番目のフォルダー以降のファイルを取得する場合)、次を使用できます。

find . -mindepth $depth ! -name test.txt

ディレクトリ構造により、次のようになります。

$ find . -mindepth 4 ! -name test.txt
./foo/bar/world/hello.txt

それはまさにあなたが期待していた通りです。


編集: これはもっと良いはずです (ただし、見苦しいですが)。 が配置されているディレクトリを検索しtest.txt、その中のすべてのファイルを検索します。利点は、親パスから完全に独立しており、自動的に計算されることです。

EXCLUDEFNAME="test.txt"; find $(find . -name "$EXCLUDEFNAME" -exec dirname {} \; -quit) -mindepth 1 ! -name "$EXCLUDEFNAME"

複数行の方が良い:

EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"

関連情報