web-dev-qa-db-ja.com

ファイルを見つけてxargsを使用して移動するにはどうすればよいですか?

いくつかのファイルを見つけて移動したい。

私はファイルを見つけることができます:

$ find /tmp/ -ctime -1 -name x*

私は~/playディレクトリにそれらを移動しようとしました:

$ find /tmp/ -ctime -1 -name x* | xargs mv ~/play/

しかし、それはうまくいきませんでした。明らかにmvには2つの引数が必要です。
mvコマンドでxargsの「現在のアイテム」を参照するかどうか(またはその方法)がわからない場合

31
Michael Durrant

最良の方法についてはステファンの答えを見て、より明白な解決策を使用しない理由(およびそれらが最も効率的でない理由)について私の答えを見てください。

xargsの_-I_オプションを使用できます。

_find /tmp/ -ctime -1 -name "x*" | xargs -I '{}' mv '{}' ~/play/
_

これは、findおよび_{}_と同様のメカニズムで機能します。私はあなたの_-name_引数も引用します(現在のディレクトリでxで始まるファイルはファイルグローブされ、findへの引数として渡されるため、期待どおりの動作が得られません!)。

ただし、manatworkで指摘されているように、xargsのマニュアルページで詳しく説明しています。

_   -I replace-str
          Replace occurrences of replace-str in the initial-arguments with
          names read from standard input.  Also, unquoted  blanks  do  not
          terminate  input  items;  instead  the  separator is the newline
          character.  Implies -x and -L 1.
_

注意すべき重要な点は、_-L 1_は、findからの出力のlineが一度に1つだけ処理されることを意味することです。これは、構文的には次と同じであることを意味します。

_find /tmp/ -ctime -1 -name "x*" -exec mv '{}' ~/play/
_

(これはeachファイルに対して単一のmv操作を実行します)。

GNU _-0_ xargs引数と_find -print0_引数を使用しても、_-I_の動作はまったく同じです。これはclone()に対するものです)各ファイルのプロセスmv

_find . -name "x*" -print0 | strace xargs -0 -I '{}' mv '{}' /tmp/other

.
.
read(0, "./foobar1/xorgslsala11\0./foobar1"..., 4096) = 870
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =     0x7fbb82fad000
open("/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=26066, ...}) = 0
mmap(NULL, 26066, PROT_READ, MAP_SHARED, 3, 0) = 0x7fbb82fa6000
close(3)                                = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 661
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 661
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,         child_tidptr=0x7fbb835af9d0) = 662
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 662
--- SIGCHLD (Child exited) @ 0 (0) ---
.
.
.
_
47
Drav Sloan

GNUツール:

find /tmp/ -ctime -1 -name 'x*' -print0 |
  xargs -r0 mv -t ~/play/

-t--target)オプションはGNU固有です。-print0-r-0、非標準であり、GNUに由来する)は、一部のBSDのような他の一部の実装でも見られます。

POSIXly:

find /tmp/ -ctime -1 -name 'x*' -exec sh -c '
  exec mv "$@" ~/play/' sh {} +

どちらも必要に応じて少数のmvコマンドを実行し、ファイル名に含まれる可能性のあるすべての文字を処理します。 GNU 1つには、findが最初のバッチの移動を開始する間、mvがファイルを探し続けるという利点があります。

すべてのファイルとディレクトリが1つのディレクトリになることに注意してください。異なるディレクトリにある複数のファイルに同じ名前が付いている場合は、衝突に注意してください。

18

おそらく、このコマンドは現在使用可能で2013年には戻っていませんが、これは私にとっては完全に機能します。

ls pattern* | xargs mv -t DESTINATION/

-tキーは、移動先のフォルダーを最初に置き、mvコマンドを解放して、最後の引数をすべて移動するファイルだけにします。

4
Nikhil VJ

あなたは以下のコマンドで試すことができ、テストされ、うまくいきました

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
0