findコマンドの後にmvコマンドを統合するにはどうすればよいですか?


61

AAA次のコマンドを使用して、パスに名前が含まれるファイルを検索しています:

find path_A -name "*AAA*"

上記のコマンドで表示される出力を考えて、これらのファイルを別のパス、たとえばに移動しますpath_B。それらのファイルを1つずつ移動する代わりに、findコマンドの直後にそれらのファイルを移動してコマンドを最適化できますか?

回答:


87

GNU mvの場合

find path_A -name '*AAA*' -exec mv -t path_B {} +

それはfindの-execオプションを使用して{}、それぞれの検索結果を順番に置き換え、指定したコマンドを実行します。で説明されているように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.  

この場合、できるだけ少ない数の操作を実行するように、+バージョンを使用しています。-execmv

   -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.

「\;」を忘れないでください execの最後に!
チャールズロス

@チャールズ・ロス:それ+は仕事をman find
ダウズする

これをありがとう!私は使用しようとし-exec mv {} path_b +ていたが、アクセス許可エラーで失敗していました。TBH、私はまだ理由を理解していませんが-exec mv -t path_b {} +、おやつを機能します!
ジェレミーデイビス

6
@JeremyDavisを使用する-exec ... {} +場合、{}はの前の最後のものでなければなりません+。これが彼が使うのmv -t destdir {} +でなく使う理由mv {} destdir +です。-exec mv {} destdir ';'代わりに1つのコールドが使用されていますが、それはmv各ファイルに対して1回実行されます。
クサラナナンダ

23

以下のようなこともできます。

find path_A -name "*AAA*" -print0 | xargs -0 -I {} mv {} path_B

どこ、

  1. -0空白または文字(改行を含む)がある場合、多くのコマンドは機能しません。このオプションは、空白のあるファイル名を処理します。
  2. -Iinitial-arguments内のreplace-strの出現を、標準入力から読み取られた名前に置き換えます。また、引用符で囲まれていない空白は入力項目を終了しません。代わりに、区切り文字は改行文字です。

テスト中

私は2つのディレクトリを作成sourcedirしてdestdir。今、私の中にたくさんのファイル作成sourcedirなどをfile1.bakfile2.bakそしてfile3 with spaces.bak

さて、コマンドを次のように実行しました、

find . -name "*.bak" -print0 | xargs -0 -I {} mv {} /destdir/

今、内部でdestdir、私が行うときls、私は、ファイルから移動していることを見ることができましたsourcedirdestdir

参照資料

http://www.cyberciti.biz/faq/linux-unix-bsd-xargs-construct-argument-lists-utility/


22

この質問に出くわすOS Xユーザーの利益のために、OS Xの構文はわずかに異なります。次のサブディレクトリを再帰的に検索したくないと仮定しますpath_A

find path_A -maxdepth 1 -name "*AAA*" -exec mv {} path_B \;

すべてのファイルを再帰的に検索する場合path_A

find path_A -name "*AAA*" -exec mv {} path_B \;

これはOS X固有の構文ではなく、find私が使用したものと同じです。良い点:(-maxdepth特にpath_Bがサブディレクトリである場合- mv既にそこにファイルを移動しようとすることを避けます!)そして\を使用します; (したがって{}は最後のパラメーターである必要はなく、通常のmv構文を使用できます)
drevicko

6

これ-execが最善の方法です。何らかの理由でこれがオプションではない場合、ループで結果を読み取ることもできます。

find path_A -name "*AAA*" -print0 | 
    while IFS= read -r -d $'\0' file; do mv "$file" path_B; done

これは安全な方法です。スペース、改行、またはその他の奇妙な文字を含むファイル名を処理できます。もっと簡単な方法が、1 ファイル名は、単純な英数字のみから構成されていない限り失敗し、あります

mv $(find path_A -name "*AAA*") path_B

ただし、whileループを使用してください。


あれば簡単な方法はまだ失敗する可能性がyour file names consist only of simple alphanumeric characters到達した場合、たとえば、ARG_MAX


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.