find + xargs: bağımsız değişken satırı çok uzun


21

Aşağıdaki gibi bir satır var:

find /foo/bar -name '*.mp4' -print0 | xargs -i {} -0 mv -t /some/path {}

ama aşağıdaki hatayı aldım:

xargs: argument line too long

Kafam karıştı. Kullanımının xargsbu soruna kesin olarak yardımcı olması gerekmiyor mu?

Not: Ben techincally kullanabileceğinizi biliyor -execBul içinde, ama zihnimin olacağı için yukarıdaki başarısız neden anlamak istiyorum xargs, etkin olduğu tartışmaya yönetilebilir içine girdi bölmek için bilmek gerekiyordu. Bu doğru değil mi?

Hepsi zsh ile.

Yanıtlar:


11

Bir şey için -ianahtarın kullanımdan kaldırılmış olması:

-i[replace-str]
     This  option  is a synonym for -Ireplace-str if replace-str is specified. 
     If the replace-str argument is missing, the effect is the same as -I{}. 
     This option is deprecated; use -I instead.

Öyleyse emrinizi bu yönde değiştirdiğimde işe yaradı:

$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}

Örnek

$ find . -print0 | xargs -I{} -0 echo {}
.
./.sshmenu
./The GIT version control system.html
./.vim_SO
./.vim_SO/README.txt
./.vim_SO/.git
./.vim_SO/.git/objects
./.vim_SO/.git/objects/pack
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.idx
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.pack
./.vim_SO/.git/objects/info
./.vim_SO/.git/refs
./.vim_SO/.git/refs/tags
...

Kullanımı -I{}

Bu komut, bu komut yapısını çalıştırdığından beri kullanılmamalıdır:

$ find -print0 ... | xargs -I{} -0 ...

örtülü bu anahtarlar açar xargs, -xve -L 1. -L 1Yapılandırır xargso komutları aradığını böylece tek bir moda üzerinden dosya çalıştırmak istiyorum.

Bu yüzden xargsburada kullanım amacını yitirir çünkü 1000 dosya verirseniz mvkomutu 1000 defa çalıştırır .

Öyleyse hangi yaklaşımı kullanmalıyım?

Böyle xargs kullanarak yapabilirsiniz:

$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path

Ya da hepsini bulduktan sonra:

$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +

Teşekkürler! "This approach shouldn't be used"Bunun yerine hangi yaklaşımın kullanılması gerektiğini söylemiştiniz ? Daha "find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir'"iyi bir çözüm olabilir mi? Eğer öyleyse, nasıl gelmez xargsbu durumda biliyorum mvo borusundan alır argümanlar içinde beslemesine komuta? (Her zaman onları en sona yerleştirir mi?)
Amelio Vazquez-Reina,

@ user815423426 - ile de genişlemiş sadece find ... -exec ...daha iyi bir yoludur veya kullanmak istiyorsanız ince too. Evet, onları her zaman en son yapar. Bu yüzden bu yönteme ihtiyaç duyuyor . xargsfind ... | xargs ... mv -t ...-t
slm

5

Seçenek -iisteğe bağlı bir argüman alır. Sonrasında bir boşluk bıraktığınızdan -i, -iseçenek için bir argüman yoktu ve bu nedenle sonraki 6 işlenenden -0bir seçenek değildi .xargs{} -0 mv -t /some/path {}

Yalnızca bu seçenekle -i, xargs yeni satır ayrılmış bir dosya adı listesi bekliyordu. Girişte muhtemelen yeni bir satır olmadığından, xargs büyük bir dosya adı gibi görünen bir şey aldı (katıştırılmış boş baytlarla, ancak xargs bunu kontrol etmedi). Çıktısının tamamını içeren bu tek dize find, maksimum komut satırı uzunluğundan daha uzundu, bu nedenle “komut satırı çok uzun” hatası.

Emriniz -i{}bunun yerine işe yarayacaktı -i {}. Alternatif olarak, kullanabilirsiniz -I {}: -Ibenzer -i, ancak zorunlu bir argüman alır, bu nedenle bir sonraki argüman seçeneğinin xargsargümanı olarak kullanılır -I. Sonra bundan sonraki argüman -0bir seçenek olarak yorumlanır, vb.

Ancak, hiç kullanmamalısınız -I {}. Kullanmanın -Iüç etkisi var:

  • -I-0Zaten yapan teklif işlemeyi kapatır .
  • -Idizeyi değiştirmek için değiştirir, ancak {}varsayılan değerdir.
  • -Ibu komutun her giriş kaydı için ayrı ayrı yürütülmesine neden olur, çünkü komutunuz ( mv -t) özellikle çağrı başına birden fazla dosyayla başa çıkmak için tasarlandığından yararsızdır .

Ya bırakın -Ive -itamamen

find /foo/bar -name '*.mp4' -print0 | xargs -0 mv -t /some/path {}

veya xargs'i bırakın ve kullanın -exec:

find /foo/bar -name '*.mp4' -exec mv -t /some/path {} +

0

Döngü için bir bash kullanmayı deneyin:

for FILE in *.mp4 ; do rm $FILE ; done

veya neler olup bittiğini görmek istiyorsanız:

for FILE in *.mp4 ; do echo Removing $FILE ; rm $FILE ; done

0

Balık kabuğunu kullanırken bunu görüyorsanız .
Bu, balıkların yeni ipi nasıl genişlettiği ile ilgilidir.{}

Balık kullanıyorsanız, yeni dizgeden kaçmanız gerekir. \{\}

| xargs -I \{\} echo \{\}

veya farklı bir değiştirme dizesi kullanın

| xargs -I ! echo !
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.