Bagaimana menyalurkan output perintah ke perintah lain?

83

Contoh:

ls | echotidak mencetak apa pun (garis kosong, sebenarnya). Saya berharap untuk mencetak daftar file.

ls | grep 'foo', di sisi lain, berfungsi seperti yang diharapkan (mencetak file dengan 'foo' di namanya).

Apa yang saya lakukan dalam situasi ini adalah sesuatu seperti: ls | while read OUT; do echo $OUT; donetetapi ini agak rumit.

Mengapa perpipaan bekerja dengan beberapa perintah, tetapi tidak dengan yang lain? Bagaimana saya bisa menghindari masalah ini?

Mihai Rotaru
sumber
2
Apa yang Anda harapkan ls | echo? mengapa tidak lari saja ls?
theomega
12
Saya menggunakan contoh paling sederhana yang menggambarkan poin saya. Saya benar-benar menghadapi masalah ini ketika saya mencoba membuat satu-liner yang akan menunjukkan objek git di toko objek dan tipenya. Jadi, saya mengirim ID objek git cat-file, tetapi itu tidak berhasil. Tampaknya, gema memiliki perilaku yang sama, jadi saya menggunakannya sebagai contoh.
Mihai Rotaru
juga melihat perintah -n untuk xargs, ia mengatakan berapa banyak argumen untuk diletakkan di bawah perintah. `... | xargs -n1 git cat-file`
Rich Homolka

Jawaban:

118

Ada perbedaan antara argumen baris perintah dan input standar. Sebuah pipa akan menghubungkan output standar dari satu proses ke input standar lainnya. Begitu

ls | echo

Menghubungkan output standar ls ke input standar echo. Baik kan? Yah, gema mengabaikan input standar dan akan membuang argumen baris perintahnya - yang tidak ada dalam kasus ini ke - stdout sendiri. Outputnya: tidak ada sama sekali.

Ada beberapa solusi dalam hal ini. Salah satunya adalah dengan menggunakan perintah yang membaca stdin dan dump ke stdout, seperti cat.

ls | cat

Akan 'bekerja', tergantung pada definisi pekerjaan Anda.

Tapi bagaimana dengan kasus umumnya. Yang Anda inginkan adalah mengonversi stdout dari satu perintah ke baris perintah yang lain. Seperti yang dikatakan orang lain, xargsadalah alat bantu kanonik dalam kasus ini, membaca baris perintahnya untuk meminta perintah dari stdinnya, dan menyusun perintah untuk dijalankan.

ls | xargs echo

Anda juga dapat mengonversi beberapa ini, menggunakan perintah substitusi $()

echo $(ls)

Akan juga melakukan apa yang Anda inginkan.

Kedua alat ini cukup inti untuk skrip shell, Anda harus mempelajari keduanya.

Untuk kelengkapan, seperti yang Anda tunjukkan dalam pertanyaan, cara dasar lain untuk mengonversi stdin ke command line args adalah readperintah builtin shell . Itu mengkonversi "kata-kata" (kata-kata seperti yang didefinisikan oleh IFSvariabel) ke variabel temp, yang dapat Anda gunakan dalam menjalankan perintah apa pun.

Homolka yang kaya
sumber
1
Jawaban informatif yang sangat membantu, terima kasih! Saat ini saya sedang belajar bash, dan saya telah melihat notasi xargs dan $ (*) sebelumnya, tetapi tidak terlalu memperhatikan mereka. Sekarang saya tahu betapa pentingnya mereka, dan pasti akan melihatnya.
Mihai Rotaru
1
xargs mungkin yang dicari OP.
Iktys
19

ls | echomencetak hanya garis kosong karena echotidak membaca input; perintah terakhir dari pipeline sebenarnya adalah echotidak mencetak apa-apa selain baris kosong.

Umumnya:

a | b

memastikan bahwa output amenjadi input dari b. Saya sarankan Anda untuk membaca Pipelinesbagian man bash.


Jika Anda benar-benar ingin menggunakan lsdan echobersama - sama, inilah beberapa contoh (sangat tidak berguna):

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
cYrus
sumber
11

Jika Anda ingin echoyang lsperintah try:

ls | xargs echo

Ini akan memanggil echodengan output dari ls.

Nathan Fellman
sumber
3
Atau ls | xargs -I {} echo {}jika Anda ingin dipanggil untuk setiap baris secara individual
Alex Abdugafarov
3

Mengapa tidak menggunakan saja:

echo `ls`

Atau jauh lebih aman:

echo "`ls -lrt`"
Urbwzrd
sumber
4
Atau bahkan adil echo *.
Kazark