
私は、ファイル を除く特定のフォルダーからファイルを再帰的にコピーするスクリプトを書こうとしていますA.extn
。ここでB/*.extn
、と はディレクトリであり、は単なる一般的な拡張機能です。私が持っているのは次のようなものです:C/*
B
C
extn
#!/usr/local/bin/zsh
setopt EXTENDED_GLOB
TMPDIR=/tmp/test
cp -pR $(dirname $0)/**~(*.foo/*|*/bar.txt|*.abc|qux.txt) $TMPDIR
しかし、これは期待どおりにパターンの否定を行いません。理由はわかっていると思います。パターンは正しいのですが ( でわかるようにecho
)、cp -R
パターンを認識できず、「想定されていない」ディレクトリに入り、そこに入るとパターンは有効ではなくなります。
上記を変更して、必要な操作を実行するにはどうすればよいですか? と を使用すれば可能だと思いますfind
がxargs
、上記の明快さに惹かれ、同様のものを好みます (ただし、これが間違った方法である場合は、別の解決策でもまったく問題ありません)。
答え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