
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"