Menggunakan xargs dengan input dari file

41

Katakanlah saya punya file dengan yang berikut ini

bob
john
sue

Sekarang ini langsung corrospond ke (dalam kasus ini) pola URL seperti http://example.com/persons/bob.tar, john.tar, sue.tar.

Saya ingin mengambil garis-garis ini dan menjalankannya xargs. Saya tidak tahu apa yang diteruskan ke perintah yang dieksekusi sekalipun. Bagaimana cara mengakses parameter baik dari prompt (katakan saya ingin cukup menggemakan setiap baris seperti cat file | xargs echo $PARAM) atau dari skrip bash.

Josh K.
sumber
Saya tidak cukup mengikuti pertanyaan, maaf. Khususnya saya tidak yakin apa artinya "Saya tidak tahu apa yang diberikan kepada perintah yang dieksekusi"
Michael Mrozek
1
@Michael: Ketika Anda menjalankan daftar, xargsia memecahnya demi baris dan memberi makan setiap baris ke dalam perintah, kan? Bagaimana saya mengaksesnya jika saya perlu mengatakan sesuatu seperti cat file | xargs curl http://example.com/[PASSED FROM FILE].tar?
Josh K

Jawaban:

70

Jawaban Michael benar, dan harus menyelesaikan masalah Anda. Lari

cat file | xargs -I % curl http://example.com/persons/%.tar

akan mengunduh file bob.tar john.tar. sue.tarseperti yang diharapkan.

TETAPI : kucing di sini tidak berguna

lebih baik gunakan:

<file xargs -I % curl http://example.com/persons/%.tar
Stefan
sumber
1
Dalam satu contoh file saya, ini mungkin tidak ideal,cat xaa xab xac xad ... xargs ...
Josh K
10
@Jos Untuk beberapa alasan orang cenderung menganggap serius penggunaan kucing yang tidak perlu di sini; Saya sudah dua kali
turun jabatan
2
sebagai catatan, Anda mendapat +1 dari saya. Saya pikir menggunakan catbenar-benar baik-baik saja, hanya ingin menambahkan lebih banyak info ... :)
Stefan
Tentunya seharusnya xargs -I % curl …( opsi xargs sebelum curldan opsi / argumennya). Paling tidak xargs curl -I %(di mana -I %dimaksudkan sebagai opsi untuk xargs , bukan curl ) tidak portabel.
Chris Johnsen
@ Chris, tangkapan yang bagus, tnx. tetap.
Stefan
16

Saya pikir Anda bertanya bagaimana memasukkan garis individual yang ditarik dari xargs'stdin di tengah-tengah perintah, alih-alih hanya menempelnya di ujung selalu. Jika demikian, -Ibendera tersebut mengambil replacement-stringargumen; xargskemudian akan menggantikan replacement-stringperintah dengan baris read dari stdin:

$ cat file | xargs -I foobar curl http://example.com/foobar.tar
Michael Mrozek
sumber
Oke, bagaimana dengan curl http://example.com/foobar.tar > foobar.tar?
Josh K
2
@ Josh K: >adalah konstruksi shell, dan tidak akan bekerja untuk xargs. Di sisi lain, curl -oakan menulis ke file bernama bukan stdout, seperti apa wget, jadi mungkin itu yang ingin Anda gunakan di sini.
ephemient
9
$ man xargs
...
       --arg-file = file
       -file
              Baca item dari file, bukan input standar. Jika Anda menggunakan ini
              opsi, stdin tetap tidak berubah ketika perintah dijalankan. Lain-
              bijaksana, stdin dialihkan dari / dev / null.
...

Anda mungkin ingin set --delimiter=/ -duntuk '\n'juga.


Di sisi lain, jika Anda hanya mencoba mengubah setiap baris dalam file menjadi URL,

File $ sed -e #. * # http: //example.com/persons/&.tar#

akan dilakukan, dan jika Anda ingin mengambil semuanya, cukup masukkan saja .| wget -i

singkat
sumber
8

cara lain dengan perulangan shell:

for i in `cat file`; do curl -I http://foo.com/$i; done

Anda juga dapat menjalankan setiap iterasi di latar belakang dengan menambahkan &sebelum titik koma terakhir - untuk unduhan yang sangat besar ini mungkin berguna

Brad Clawsie
sumber
2
Anda telah jatuh cinta pada salah satu kesalahan klasik ! <- tautan rusak, inilah versi yang di-cache: Penggunaan Cat Award yang Tidak Berguna .
Sorpigal
@ Kaligal Url itu rusak. Apa itu 'Kesalahan Klasik'?
starbeamrainbowlabs
@ starbeamrainbowlabs - penggunaan cat yang tidak berguna, saya telah meletakkan versi cache dari tautan tersebut di komentar di atas.
slm
@starbeamrainbowlabs: Saya secara khusus menghubungkan ke Dangerous Backticks , tetapi penggunaan kucing juga tidak perlu jika Anda mengubah ke konstruksi sementara:while IFS= read i ; do curl ... ; done < file
Sorpigal
3

Dengan GNU Parallel Anda dapat melakukan:

cat urls | parallel curl {} ">" {/}

Atau:

cat persons | parallel curl http://example.com/persons/{}.tar ">" {}.tar

Tonton video intro untuk GNU Parallel untuk mempelajari lebih lanjut: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
sumber
1

while read VAR; do ... done loop sederhana namun sangat fleksibel:

while read word; do wget http://example.com/persons/$word; done < file
musiphil
sumber
0

Ini adalah versi yang lebih umum dari jawaban Stefan: tetapi saya menggunakan awk di tengah untuk menyiapkan "string" yang tepat yang ingin saya jalankan xargs. Dan kemudian xargs menggunakan bash untuk melakukan "pekerjaan" yang sebenarnya.

Ini agak berlebihan untuk contoh ini, tetapi ini adalah solusi umum yang dengan beberapa modifikasi dapat menyelesaikan banyak masalah ...

cat file | awk '{print "curl http://example.com/persons/"$1".tar"}' | xargs -0 bash -c
Johan
sumber