web-dev-qa-db-ja.com

find -execcpの問題

この例を考えてみましょう。

touch test0
touch timestamp
touch test1
Sudo find /var/www/import -iname 'test*' -newer timestamp -exec cp {} new \;

実際にはファイルtest1をコピーしますが、次のメッセージを返します。

cp: `/var/www/import/new/test1' and `new/test1' are the same file

私は何が間違っているのですか?

2番目の質問、このコマンドで「+」を使用して、ファイルを1つの「バンドル」にコピーできますか?何千ものファイルがあります!

5
Mike

私は何が間違っているのですか?

それで大丈夫です。 findnewですでにコピーされたファイルを見つけて再度コピーしようとするため、警告メッセージが表示されます。

このコマンドで「+」を使用して、ファイルを1つの「バンドル」にコピーできますか?何千ものファイルがあります!

はい。ただし、次のようにコマンドを変更する必要があります。

find /var/www/import -iname 'test*' -newer timestamp -exec cp -t new {} +

この場合、{}はexecステートメントの最後になければならないためです。

12
rush

echoの前にcpを追加すると、それが実行されていることがわかります。

cp new/test1 new
cp test1 new

これは、findが現在のディレクトリを検索するだけでなく、すべてのサブディレクトリを検索するためです。

代替案:

findに、サブディレクトリを調べないように指示します。

find /var/www/import -maxdepth 1 \
    -iname 'test*' -newer timestamp -exec cp {} new \;

findサブディレクトリを無視するようにnewに指示します。

find /var/www/import -type d -name new -Prune -o \
    -iname 'test*' -newer timestamp -exec cp {} new \;

ファイルを/var/www/importの外部のディレクトリにコピーします。

find /var/www/import \
    -iname 'test*' -newer timestamp -exec cp {} /var/www/import.new \;

ただし、サブディレクトリがある場合は、同じ名前のファイルが失われることになります。

例えばあなたが持っている場合

test0
test1
scripts/test1

その後、あなたは

test0
test1
new/test1
scripts/test1

どのtest1newにコピーされましたか?

これを処理する方法はいくつかありますが、私が考えることができる最も簡単で効率的な方法は、cp --parentsを使用することです。

cd /var/www/import
find . -type d -name new -Prune -o \
    -type f -iname 'test*' -newer timestamp -exec cp --parents {} new \;

それはあなたに与えるでしょう

test0
test1
new/test1
new/scripts/test1
scripts/test1

ラッシュはすでにあなたの質問の2番目の部分に答えているので、私は彼を繰り返しません。

4
Mikel