findを他のコマンドと組み合わせる:いつ-execを使用し、いつパイプを使用しますか? [コピー]

findを他のコマンドと組み合わせる:いつ-execを使用し、いつパイプを使用しますか? [コピー]

ファイルとディレクトリを見つけるためにfindコマンド自体を使用する方法を学びましたが、ファイル/フォルダに対して特定のタスクを実行すると混乱します。

次のコマンドを実行します。

find . -type f -iname "*.cr2" 

上記で見つけたファイルを新しいディレクトリにコピーしたい場合は、copy(cp)とパイプラインを使用する方法を自然に考えてみましょう|

find . -type f -iname "*.cr2" | cp \destination_directory

私の場合、サブフォルダのレベルは1つのフォルダに入れ子になり、ドライブ全体にすべての写真が保存され、クリーンアップを開始できます。

しかし、人々は引き続きパラメータを使用するように言います。だから私の質問は、いつパイプを使うべきか、いつこのようなコマンドを使うべきかを-execどうやって知ることができるかということです。|-exec

 find . -name "*.pdf" -type f -exec cp {} ./pdfsfolder \;

編集する

以下の提案されたソリューションは、一意のファイル名を持つファイルのみをコピーします。 cpは、file.txtをコピーせずにfile.txtに置き換えないと言います。多くのファイルをコピーしたが、同じ名前のファイルがあるかどうかわからない場合は、いくつかのファイルをコピーしてファイル名がある場合は、どのように名前を変更しますか?

提案されたソリューション

find . -type f -iname "*.txt" -print0 | xargs -0 cp -t /home/josh/Documents/copy/

/home/josh/documents/copy はコンテンツを移動したいディレクトリです。

答え1

あなたの家は間違っていますが、まずいくつかの背景情報があります。

識別する必要がある2つの用途は次のとおりです-exec

  • 見つかった単一の\;項目に置き換えられます。{}
  • コマンドラインが受け入れられるだけのアイテムに置き換えられ+ます。{}

したがって、使用例では、-exec見つかったエントリ数だけコマンドを呼び出します。cpfind

使用find ... -exec cmd {} ... +効率は、findの出力を複数の入力名を処理するコマンドにパイプするのと似ています。

-execまた、空白のあるファイル名/パスはうまく処理されますが、findの出力を別のプログラムにパイプするときに問題が発生する可能性があることを考慮する必要があります。したがって、stdinのファイル名のリストを必要とする一部のプログラムは、ファイル名を通常(-0または--null)で区切ることを選択できます。find以下を指定して、オプションで次のプログラムに提供できます。-print0


今、あなたの例を見てください。

find . -type f -iname "*.cr2" | cp destination_directory

cpが標準入力から読み取られないため、見つかったファイルはコピーされません。以下を使用する必要があります。

find . -type f -iname "*.cr2" | xargs cp -t destination_directory

または、空白のあるパスを処理します。

find . -type f -iname "*.cr2" -print0 | xargs -0 cp -t destination_directory

ほぼ同じ効率で次のことができます。

find . -type f -iname "*.cr2" -exec cp -t destination_directory {} +

(G-Manが指摘したように{}最後になければなりません+)上記のすべてが適用されます。いいえこれを行うには、ターゲットディレクトリの下に階層を構築し、長い習慣に基づいてソースディレクトリが単純であっても、以下を使用しますcpio

find . -type f -iname "*.cr2" -print0 | cpio -pdmv0 destination_directory

その過程で行ったことをよく説明します。


関連部品man find:

-exec command ;
       Execute command; true if 0 status is returned.   All  following
       arguments  to  find  are  taken  to be arguments to the command
       until an argument consisting of `;' is encountered.  The string
       `{}'  is  replaced  by  the  current  file name being processed
       everywhere it occurs in the arguments to the command, not  just
       in  arguments  where  it is alone, as in some versions of find.
       Both of these constructions might need to be  escaped  (with  a
       `\')  or  quoted  to  protect them from expansion by the shell.
       See the EXAMPLES section for examples of the use of  the  -exec
       option.   The  specified  command  is run once for each matched
       file.  The command  is  executed  in  the  starting  directory.
       There  are unavoidable security problems surrounding use of the
       -exec action; you should use the -execdir option instead.

-exec command {} +
       This variant of the -exec action runs the specified command  on
       the  selected files, but the command line is built by appending
       each selected file name at the end; the total number of invoca‐
       tions  of  the  command  will  be  much less than the number of
       matched files.  The command line is built in much the same  way
       that xargs builds its command lines.  Only one instance of `{}'
       is allowed within the command.  The command is executed in  the
       starting directory.

関連情報