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


28

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

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

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

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

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

しかし、それはうまくいきませんでした。明らかに、mvには2つの引数が必要です。
mvコマンドでxargs 'current item'を参照するかどうか(またはその方法)がわかりませんか?


3
どうして?プレースホルダーは-Ifind . | xargs -I'{}' mv '{}' ~/play/で使用できますが、男が言うように、「Implies -xand -L 1。」シンプルに保ち、使いfind . -exec mv '{}' ~/play/ \;
やすく

よろしければ投票として回答を投稿してください:)
マイケルデュラント

理由を尋ねたところ、私には意味が分からなかったような感覚がありました。Drav Sloanが暗黙のオプションについてのメモを追加すると、彼の答えは、私が書くことができる最高のものになります。だからそれで行く方がいい。
マナトワーク


@manatwork私はそれらのポイントを反映するために私の答えを編集しました:)
Drav Sloan

回答:


43

最良の方法についてはStephaneの回答をご覧ください。より明白なソリューションを使用しない理由(および最も効率的ではない理由)については私の回答をご覧ください。

次の-Iオプションを使用できますxargs

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

これに似た仕組みで動作findして{}。また、-name引数を引用します(x現在のディレクトリで始まるファイルはファイル化され、findの引数として渡されるため、予期した動作が得られません!)。

ただし、manatworkで指摘されているように、xargsmanページに詳細があります。

   -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一度に1 の出力のみfindが処理されることを意味します。これは、構文的には次と同じことを意味します。

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

(ファイルごとに 1つのmv操作を実行します)。

GNU -0xargs引数を使用しても、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) ---
.
.
.

これは、ファイル名に改行、一重引用符、二重引用符、または円記号が含まれていないことを前提としています。
ステファンシャゼル

17

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の方には、最初のバッチの移動findmv開始しながらファイルを探し続けるという利点があります。

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


このソリューションはmv、すべての引数(または、提供されている場合はすべての-Lまたは-n)に対して1回呼び出すため、パフォーマンスがはるかに優れています。そうしないとmv、各ファイルの呼び出しが古くなります(そして遅くなります)。
r2evans

1

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

ls pattern* | xargs mv -t DESTINATION/

-t解放先のフォルダ最初のキープット、mvファイルだけを移動するようなコマンドは、すべての最後の引数を持っています。


1
これは私のために働いた最も簡単なソリューションでした
ptetteh227

0

あなたは以下のコマンドで試してテストでき、うまく動作します

find /tmp/ -ctime -1 -type f -name "x*" -exec mv -t ~/play/ {} \;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.