Mengarahkan konten file ke perintah "echo"

41

Saya memiliki file bernama my_file.txtyang isinya hanya string Hello. Bagaimana saya bisa mengarahkan kontennya ke perintah echo?

Saya tahu saya memiliki perintah less, cat, more... tapi aku harus melakukannya dengan echo.

Saya mencoba ini:

$ cat my_file.txt | echo

dan juga ini:

$ echo < my_file.txt

Tetapi dalam kedua kasus itu hanya muncul kosong di stdout, bukan konten my_file.txt.

Bagaimana saya bisa melakukan itu?

danielmbcn
sumber
7
Mengapa Anda bersikeras menggunakan echo?
Kevin
7
@ Kevin, mungkin akhirnya dia ingin memperluas urutan pelarian ANSI C ( \n, b...) dalam file, yang akan menjadi penggunaan yang valid echo(setidaknya standar echo). Atau mungkin dia ingin mengerti mengapa itu tidak bekerja seperti itu. Bagaimanapun, tidak ada alasan untuk menurunkan IMO.
Stéphane Chazelas
3
Saya datang ke sini karena saya ingin tahu mengapa itu tidak berfungsi ketika saya melakukan echo <file.txt. Tampaknya pertanyaan yang masuk akal untuk dimiliki di SE, jawabannya sangat membantu. +1 dari saya.
neuronet

Jawaban:

53

Anda dapat mengalihkan semua yang Anda inginkan echotetapi tidak akan melakukan apa-apa dengannya. echotidak membaca input standarnya. Yang dilakukannya hanyalah menulis ke output standar, argumennya dipisahkan oleh karakter spasi dan diakhiri oleh karakter baris baru (dan dengan beberapa echoimplementasi dengan beberapa urutan escape di dalamnya diperluas dan / atau argumen dimulai dengan -kemungkinan diperlakukan sebagai opsi).

Jika Anda ingin echomenampilkan konten file, Anda harus meneruskan konten itu sebagai argumen echo. Sesuatu seperti:

echo "$(cat my_file.txt)"

Perhatikan bahwa $(...)strip baris baru karakter s dari output dari yang catperintah, dan echomenambahkan satu kembali.

Perhatikan juga bahwa kecuali dengan zsh, Anda tidak dapat melewatkan karakter NUL dalam argumen perintah, sehingga di atas biasanya tidak akan bekerja dengan file biner. yashjuga akan menghapus byte yang tidak membentuk bagian dari karakter yang valid.

Jika alasan karena ingin melakukan itu adalah karena Anda ingin echomemperluas \n, \b, \0351... escape sequence dalam file (seperti conformant UNIX echoimplementasi lakukan, tetapi tidak semua ), maka Anda lebih suka menggunakan printfgantinya :

printf '%b\n' "$(cat my_file.txt)"

Berlawanan dengan itu echo, yang portabel dan tidak akan memiliki masalah jika konten file dimulai -.


Sebagai alternatif untuk $(cat file), dengan ksh, zshdan bash, satu juga dapat melakukan:$(<file) . Itu adalah operator khusus di mana shell sebagai lawan catmembaca konten file untuk membuat ekspansi. Masih menghapus baris baru yang tertinggal dan tersedak pada byte NUL kecuali pada zsh. Dalam bash, itu masih membutuhkan proses tambahan. Juga perhatikan bahwa satu perbedaan adalah bahwa Anda tidak akan mendapatkan kesalahan jika mencoba membaca file direktori jenis seperti itu. Selain itu, meskipun $(< file)spesial, $(< file; other command)tidak (dalam zsh, ketika tidak meniru shell lain, itu masih akan memperluas konten file, dengan menjalankan perintah implisit $READNULLCMD (biasanya pager)).

Stéphane Chazelas
sumber
3
Dalam kedua bash dan zsh Anda dapat melewatkan catdan hanya memiliki shell membacanya secara langsung: echo "$(<my_file.txt)".
Kevin
1
Ya, dengan ksh , zsh , dan bash yang dapat Anda gunakan $(<filename).
Dimitre Radoulov
Terima kasih banyak, itulah yang saya butuhkan dan itu berhasil! :-)
danielmbcn
@Kevin, Dimitre, ditambahkan sekarang.
Stéphane Chazelas
4

Menambahkan ke jawaban lain, Anda juga dapat mencoba pengalihan input cat

echo $(<my_file.txt)

atau

echo `<my_file.txt`

$()dan `` melakukan hal yang sama, mereka menjalankan perintah di dalam ruang lingkup mereka dan memberikan output ke shell seolah-olah itu diberikan sebagai input oleh pengguna. Satu-satunya perbedaan antara keduanya adalah $ () dapat bersifat rekursif dan `` tidak dapat bersifat rekursif.

GypsyCosmonaut
sumber
2

Jawaban sederhana: Anda tidak bisa. echo(baik itu shell built-in atau biner biasa) tidak memproses input standar - itu hanya satu arah.

peterph
sumber
Pertanyaannya adalah, mengapa Anda sebenarnya ingin melakukan ini?
peterph
2

Seperti yang dikatakan,

Jika Anda ingin echomenampilkan konten file, Anda harus meneruskan konten itu sebagai argumenecho

Misalnya, Anda dapat melakukannya dengan ini xargs(mengingat bahwa Anda perlu mengaktifkan interpretasi backslash lolos ):

$ cat my_file.txt | xargs echo -e

Atau hanya apa yang Anda minta (tanpa interpretasi urutan lolos ):

$ cat my_file.txt | xargs echo
kenichi
sumber
Perhatikan bahwa ketika menggunakan xargs echo(sama dengan xargsbtw seperti echohalnya perintah default), itu adalah echoperintah dari sistem file yang akan dijalankan, bukan echoperintah builtin shell . Perhatikan juga bahwa xargsmengharapkan inputnya dalam format yang sangat spesifik (di mana kosong, baris baru, kutipan, garis miring terbalik memiliki arti khusus). cattidak masuk akal di sini karena ada hanya satu file ke concatenate (sama seperti < file.txt xargs echoPerhatikan bahwa Unix compliant. echos melakukan ekspansi melarikan diri backslash secara default dan output -epada echo -e.
Stéphane Chazelas
0

Dalam bash, hal-hal berikut juga harus berfungsi:

echo `cat my_file.txt`

Bagian dalam backticks digantikan oleh output dari perintah itu, yaitu dalam hal ini diganti dengan konten file.

Motlib
sumber
Benar, backticks bekerja seperti $( . . . ). Orang yang menggunakan $()biasanya lebih suka karena Anda bisa membuat sarang. Pertanyaan ini sudah tua, namun, jauh lebih memuaskan untuk menjawab pertanyaan yang belum dijawab!
Law29
Tidak terlalu. Ada perbedaan yang halus. Ketika bentuk tanda centang kembali digunakan, tanda garis miring mempertahankan makna literalnya kecuali bila diikuti oleh $, `, atau \. Centang-balik pertama yang tidak diawali dengan backslash mengakhiri perintah. Saat menggunakan formulir $ (,,,), semua karakter di antara tanda kurung membuat perintah.
fpmurphy
Karena substitusi perintah tidak dikutip, operator split + glob akan diterapkan padanya. Misalnya jika my_file.txtberisi *, itu akan mencetak daftar nama file di direktori saat ini.
Stéphane Chazelas