出力が tar に送られると、「find」のフィルターは無視されます

出力が tar に送られると、「find」のフィルターは無視されます

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

test/
test/1/
test/foo2bar/
test/3/

ディレクトリ「test」を圧縮したいのですが、サブディレクトリ(深さは未定義)にあるもの、つまり文字列「1」または「2」を含むものはすべて除外します。bashシェルでは、次のように使用します。探すそしてその出力をタール最初にテストする探す:

find test/ -not -path "*1*" -not -path "*2*"

出力:

test/
test/3

素晴らしい。それで私はそれを組み合わせてタール:

find test/ -not -path "*1*" -not -path "*2*" | tar -czvf test.tar.gz --files-from -

出力:

test/
test/3/
test/1/
test/foo2bar/
test/3/

実際、アーカイブには「test/1」と「test/foo2bar」の両方が存在します。これらの引数は find 出力には存在しないはずなのに、なぜ tar に渡されたのでしょうか?

答え1

@cuonglmの発言を補足すると、tarデフォルトでは再帰的に動作します。ディレクトリ名を渡すと、コンテンツそのディレクトリの。

findディレクトリではなくファイル名のみを返すようにコマンドを変更することもできます...

find test/ -type f -not -path "*1*" -not -path "*2*" |
tar -czvf test.tar.gz --files-from -

--no-recursion代わりにフラグを使用して次の操作を行うこともできますtar

find test/ -not -path "*1*" -not -path "*2*" | 
tar -czvf test.tar.gz --no-recursion --files-from - 

その結果は次のようになります:

test/
test/3/

この--no-recursionフラグは GNU tar に固有のものです。他のものを使用している場合は、適切なマニュアル ページを参照して、同様の機能が利用可能かどうかを確認してください。

findコマンドは除外されることに注意してくださいファイルパスおよびディレクトリに1または を含むもの。2

答え2

--excludeGNU tar では、名前に基づいてファイルを除外するオプションも使用できます。

$ tar --exclude "*1*" --exclude "*2*" -cvf foo.tar  test/
test/
test/3/

除外パターンを読み取るファイルを受け取る-Xまたはもあります。--exclude-from


ただし、これは名前にまたは をfind -not -path "*1*"含むファイルも除外します。スキップするには、12ディレクトリ名前がパターンに一致する場合は、find -pruneと を使用しますtar --no-recursion

$ touch test/3/blah.1
$ find test/ -type d \( -name "*1*" -o -name "*2*" \) -prune -o -print |
   tar cvf test.tar --files-from - --no-recursion
test/
test/3/
test/3/blah.1

(少なくともGNU tarとFreeBSD tarにはあります--no-recursion

関連情報