cp で使用するために zsh グロブパターンを変更する

cp で使用するために zsh グロブパターンを変更する

私は、ファイル を除く特定のフォルダーからファイルを再帰的にコピーするスクリプトを書こうとしていますA.extn。ここでB/*.extn、と はディレクトリであり、は単なる一般的な拡張機能です。私が持っているのは次のようなものです:C/*BCextn

#!/usr/local/bin/zsh
setopt EXTENDED_GLOB
TMPDIR=/tmp/test

cp -pR $(dirname $0)/**~(*.foo/*|*/bar.txt|*.abc|qux.txt) $TMPDIR

しかし、これは期待どおりにパターンの否定を行いません。理由はわかっていると思います。パターンは正しいのですが ( でわかるようにecho)、cp -Rパターンを認識できず、「想定されていない」ディレクトリに入り、そこに入るとパターンは有効ではなくなります。

上記を変更して、必要な操作を実行するにはどうすればよいですか? と を使用すれば可能だと思いますfindxargs、上記の明快さに惹かれ、同様のものを好みます (ただし、これが間違った方法である場合は、別の解決策でもまったく問題ありません)。

答え1

パターンはcp実行前に展開されるため、そのコマンドでは不明であることは正しいです。

ではなく--parentsオプションを使用すると、目的を達成できる場合があります。これにより、パターンに一致するファイルのみがコピーされますが、末尾のファイル名だけでなく、指定された完全なパス名が使用されます。cp-R

しかし、このオプションは移植性がありません。私の知る限り、これは cp の GNU バージョンでのみサポートされています。

答え2

パターンはコピーしたくないファイルを除外しているかもしれませんが、それらのファイルを含むディレクトリは除外しておらず、cp再帰的にコピーするように指示しています。そのため、ファイルはとにかくコピーされます。それよりも悪いのは、次のようなソースツリーがある場合です。

foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt

パターンは に拡張され、foo hello hello/world hello/world/wibble.txt最終的に次のファイルが作成されます$TMPDIR

foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt
wibble.txt
world
world/wibble.txt

これは、パターンが「有効ではなくなった」ということとは関係ありません。パターンはシェルによって拡張され、cpファイルのリストのみを参照します。

再帰的なトラバーサルを実行するときにファイルを除外できるコピー ツールを使用する必要があります。

これには zcp を使用できますが、ディレクトリはコピーされず、ターゲット ディレクトリは自動的に作成されません。この作業に最も簡単なツールは rsync です。Pax も別のオプションです。

rsync -a --exclude='*.foo/*' --exclude='bar.txt' --exclude='*.abc' --exclude='/qux.txt' $(dirname $0) $TMPDIR

関連情報