Mengapa xargs melewatkan argumen pertama saat meneruskan ke subkulit?

8

Mencari cara untuk memanggil lebih dari satu perintah dalam xargs one-liner, saya menemukan rekomendasi di findutils untuk memanggil shell dari xargs seperti ini:

$ find ... | xargs sh -c 'command $@'

Lucunya, jika saya menggunakan xargs seperti itu, untuk beberapa alasan ia melewatkan argumen pertama:

$ seq 10 | xargs bash -c 'echo $@'
2 3 4 5 6 7 8 9 10
$ seq 10 | xargs -n2 bash -c 'echo $@'
2
4
6
8
10

Apakah ada yang salah dengan versi shell atau xargs saya? Apakah dokumentasi itu tidak akurat?

Menggunakan xargs (GNU findutils) 4.4.2 dan GNU bash, versi 4.3.11 (1) -release .

elias
sumber

Jawaban:

13

Halaman manual [bash] mengatakan: " -c stringJika opsi -c hadir, maka perintah dibaca dari string. Jika ada argumen setelah string, mereka ditugaskan ke parameter posisi, dimulai dengan $ 0. " - Kuncinya adalah $ 0 ; itu berarti bahwa nama perintah akan menjadi argumen pertama.

seq 10 | xargs sh -c 'echo $@; echo $0' sh
1 2 3 4 5 6 7 8 9 10
sh
Janis
sumber
Oh begitu! jadi itu sebabnya dokumen menuliskannya movedi akhir contoh! Saya harus membaca dengan lebih cermat ... Terima kasih! =)
elias
11

Mengapa xargs melewatkan argumen pertama saat meneruskan ke subkulit?

Tidak. Bash memberikan argumen pertama menjadi $ 0:

$ seq 10 | xargs -n2 bash -c 'echo $0'
1
3
5
7
9

$@ekspansi ke $1 $2 $3.... Akibatnya, nilai $0tidak termasuk dalam $@.

John1024
sumber
Penjelasan ini jauh lebih jelas daripada @ Janis, tetapi jawaban Janis termasuk solusi yang baik untuk masalah ini.
alexis