xargs - her argümanı bir parametreyle ekle


Yanıtlar:


13

Bunu yapmanın bir yolu:

echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand

Bu a, boşluklar, yeni satırlar, tırnak işaretleri veya ters eğik çizgiler içerdiğini varsayar bve ciçermez. :)

GNU ile findutilgenel durumu ele alabilirsiniz, ancak biraz daha karmaşıktır:

echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand

Sen yerini alabilecek |bu görünmez, diğer bazı karakter ile ayırıcı a, bya c.

Düzenleme: As @MichaelMol notlar, tartışmaların çok uzun bir liste ile geçirilebilir argümanlar maksimum uzunluğu taşan bir riski vardır mycommand. Bu olduğunda, son xargslisteyi böler ve başka bir kopyasını çalıştırır mycommandve bunun sonlandırılmamış olarak bırakılması riski vardır -f. Bu durum hakkında endişeleniyorsanız, xargs -0yukarıdaki sonuncuyu böyle bir şeyle değiştirebilirsiniz :

... | xargs -x -0 mycommand

Bu sorunu çözmez, ancak mycommandargümanlar listesi çok uzun olduğunda çalışmayı iptal eder.


1
Eşleştirilmiş parametresini aşma ARG_MAXve -fayrılma riski oldukça çirkin .
Michael Mol

@MichaelMol Bu iyi bir nokta, ama hakkında daha fazla bilgi sahibi olmadan bu durumu ele almanın anlamlı bir yolu olduğunu düşünmüyorum mycommand. Her zaman -xsonuncuya ekleyebilirsiniz xargs.
Satō Katsura

Bence uygun çözüm muhtemelen hiç kullanmak değildir xargsve sadece kullanılabiliyorsa kullanmaktır find. Bu çözüm tehlikelidir; en azından cevabınızdaki başarısızlık durumunda uyarmalısınız.
Michael Mol

@MichaelMol findÖzellikle ilk argümanlar dosya adı olmadığında nasıl daha iyi bir genel çözüm olacağını göremiyorum . :)
Satō Katsura

İlk argümanların ne olduğunu bilmiyoruz; soruna ilham veren senaryoyu değil, sadece verilen örneği görüyoruz. Sezgi, adında bir argümanla -fve lsörnekleme için kullanılan örnek bir araçla , @ kullanıcı olmayanların dosya adları ile uğraştığını öne sürer . Ve verilen findsunuyor -execsize sağlayan argüman, inşa bir komut satırı, 's cezası. ( mycommandBir kereden fazla çalışmasına izin verildiği sürece . Değilse, o zaman xargsburada kullanımı ile ilgili başka bir sorunumuz var ...)
Michael Mol

5

Bunu ele almanın daha iyi bir yolu (IMO):

  • içinde zsh:

    l=(a b c)
    mycommand -f$^l
    

    veya argüman seçeneğe eklenmeyecek şekilde dizi sıkıştırma özelliğini kullanarak:

    l=(a b c) o=(-f)
    mycommand "${o:^^l}"
    

    Bu şekilde, ldizi boş öğeler veya boşluk veya başka herhangi bir sorunlu karakter içeren öğeler içeriyorsa yine de çalışır xargs. Misal:

    $ l=(a '' '"' 'x y' c) o=(-f)
    $ printf '<%s>\n' "${o:^^l}"
    <-f>
    <a>
    <-f>
    <>
    <-f>
    <">
    <-f>
    <x y>
    <-f>
    <c>
    
  • içinde rc:

    l=(a b c)
    mycommand -f$l
    
  • içinde fish:

    set l a b c
    mycommand -f$l
    

(AFAIK rcve fishdizi sıkıştırması yok)

Eski tarz Bourne benzeri mermilerle bashher zaman yapabilirsin (yine de $@dizinin elemanlarında herhangi bir karaktere izin verir ):

set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"

1
Bunu bash'de yapmanın başka bir yolu da adlandırılmış bir dizi değişkenidir. for i; do args+=('-f' "$i");done; mycommand "${args[@]}". IDK bu daha hızlıysa, ancak bir diziye 2 öğe eklemek O (n) gibi görünüyor, setdöngü büyük olasılıkla her seferinde birikmiş arg listesini kopyalar ve yeniden ayrıştırır (O (n ^ 2)).
Peter Cordes
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.