Perintah untuk menampilkan konten file ke stdout?


28

Saya tahu catbisa melakukan ini, tetapi tujuan utamanya adalah untuk menyatukan daripada hanya menampilkan konten.

Saya juga tahu tentang lessdan more, tetapi saya sedang mencari sesuatu yang sederhana ( bukan pager ) yang hanya menampilkan isi file ke terminal dan itu dibuat khusus untuk ini, jika ada hal seperti itu.


1
Sebenarnya 99% kali Anda menggunakan cat adalah untuk menampilkan file daripada menyatukan apa pun.
LatinSuD

1
@LatinSuD - 100% dari waktu - catmenggabungkan.
mikeserv

@ mikeserv: Ini adalah masalah apa yang Anda maksud dengan melakukan operasi; penggunaan bahasa normal akan menyiratkan itu dilakukan setidaknya sekali. "Mencetak" string kosong tidak melibatkan pencetakan karakter apa pun; akan adil untuk mengatakan itu tidak mencetak apa pun. Sekarang komputasi a+b+cmelibatkan melakukan 2 penambahan, dan komputasi atidak melibatkan penambahan apa pun. Demikian pula mengeksekusi cat ftidak melibatkan penggabungan apa pun (meskipun ini adalah satu-satunya hal yang "berarti urutan satu file" bisa berarti).
Marc van Leeuwen

2
@ mikeserv: Saya tidak mengerti maksud Anda dengan + keluar. Tentu catmembaca file dan menulis file lain (stream), tetapi itu tidak berarti itu adalah gabungan dari apa pun. Haruskah Anda maksud yang cat fsebenarnya dilakukan cat - f, itu tidak benar.
Marc van Leeuwen

1
@ Bingung00: catbenar-benar dimaksudkan untuk menyatukan ( cat file1 file2akan menggabungkan kedua file ke stdout). Tetapi efek sampingnya adalah, ketika hanya memiliki 1 file sebagai argumen, ia mengeluarkan satu file untuk stdout (ke mana pun pergi, baik terminal Anda, atau diarahkan ke sesuatu). Jadi tidak ada perintah lain yang dibuat hanya untuk keluaran pada stdout, seperti yang catada dan dibiarkan saja. Karena itu Anda ingin menggunakannya cat.
Olivier Dulac

Jawaban:


37

Yang paling jelas adalah cat. Tapi, lihat juga headdan tail. Ada juga utillities shell lain untuk mencetak file baris demi baris: sed, awk, grep. Tapi itu adalah untuk mengganti konten file atau mencari di dalam file.

Saya membuat beberapa tes untuk memperkirakan mana yang paling efektif. Saya menjalankan semua palung straceuntuk melihat yang membuat panggilan sistem paling sedikit. File saya memiliki 1.275 baris.

  • awk: 1355 panggilan sistem
  • cat: 51 panggilan sistem
  • grep: 1337 panggilan sistem
  • head: 93 panggilan sistem
  • tail: 130 panggilan sistem
  • sed: 1378 panggilan sistem

Seperti yang Anda lihat, bahkan jika catdirancang untuk menggabungkan file, itu adalah yang tercepat dan paling efektif. sed, awkdan grepmencetak file baris demi baris, itulah sebabnya mereka memiliki lebih dari 1.275 panggilan sistem.


8
Ide bagus untuk menghitung syscalls!
Jan

1
+1, jawabannya lebih akurat (tentang arti kucing), lebih lengkap (alternatif), dan diteliti (syscall)
Olivier Dulac

23

Saya tahu catbisa melakukan ini, tetapi tujuan utamanya adalah untuk menyatukan daripada hanya menampilkan konten.

Tujuannya catpersis seperti itu, membaca file dan output ke stdout.


1
Tetapi cat --helpmengatakan "FIAT Rangkaian, atau input standar, ke output standar". Saya tidak ingin menggabungkan apa pun
confused00

18
Percaya atau tidak, kucing memang yang Anda cari.
Jan

5
Tidak, @ingung00, Jan benar. Masalahnya adalah - terminal adalah stdout - Anda lihat? lakukan readlink /dev/fd/1misalnya - Anda harus mendapatkan nama tty Anda di sana jika berjalan pada prompt standar. Jadi menggabungkan input ke output adalah apa yang Anda minta lakukan.
mikeserv

2
@ mikeserv Ya, saya mengerti maksud Anda, saya kira saya terlalu fokus pada arti 'concatenate'.
confused00

3
Logikanya adalah, mencetak isi dari satu file hanyalah kasus khusus untuk mencetak konten dari satu atau lebih file secara berurutan.
zwol

10

Pertama, catmenulis ke output standar, yang belum tentu terminal, bahkan jika catdiketik sebagai bagian dari perintah ke shell interaktif. Jika Anda benar-benar membutuhkan sesuatu untuk ditulis ke terminal bahkan ketika output standar dialihkan, itu tidak mudah (Anda perlu menentukan terminal mana, dan mungkin bahkan tidak ada satu jika perintah dijalankan dari skrip), meskipun satu dapat (ab) menggunakan output kesalahan standar jika perintah hanyalah bagian dari pipa. Tetapi karena Anda menunjukkan bahwa catsebenarnya melakukan pekerjaan itu, saya kira Anda tidak bertanya tentang situasi seperti itu.

Jika tujuan Anda adalah mengirimkan apa yang ditulis ke output standar ke dalam pipa, maka menggunakan catakan memenuhi syarat untuk Penggunaan Cat Award yang Tidak Berguna , karena cat file | pipeline(di mana pipelinesingkatan dari pipa apa pun) dapat dilakukan dengan lebih efisien <file pipeline. Tetapi sekali lagi, dari kata-kata Anda, saya menyimpulkan bahwa ini bukan niat Anda.

Jadi tidak begitu jelas apa yang Anda khawatirkan. Jika Anda merasa catterlalu lama untuk mengetik, Anda dapat mendefinisikan alias satu atau dua karakter (masih ada beberapa nama seperti itu yang tetap tidak digunakan dalam Unix standar). Namun jika Anda khawatir catmenghabiskan siklus yang tidak berguna, Anda seharusnya tidak melakukannya.

Jika ada program nullyang tidak menggunakan argumen dan hanya menyalin input standar ke output standar (objek netral untuk jaringan pipa), Anda dapat melakukan apa yang Anda inginkan <file null. Tidak ada program seperti itu, meskipun akan mudah untuk menulis (program C dengan mainfungsi satu-baris dapat melakukan pekerjaan itu), tetapi memanggil cattanpa argumen (atau cat -jika Anda ingin secara eksplisit) melakukan hal itu.

Jika ada nocatprogram yang mengambil tepat satu argumen nama file, mencoba untuk membuka file, mengeluh jika tidak bisa, dan sebaliknya mulai menyalin dari file ke output standar, maka itu akan menjadi apa yang Anda minta. Hanya sedikit lebih sulit untuk menulis daripada null, pekerjaan utama adalah membuka file, menguji, dan mungkin mengeluh (jika Anda teliti, Anda mungkin juga ingin memasukkan tes bahwa ada satu argumen, dan mengeluh sebaliknya). Tetapi sekali lagi cat, sekarang disediakan dengan satu argumen, tidak hanya itu, sehingga tidak perlu untuk nocatprogram apa pun .

Setelah Anda berhasil menulis nocatprogram, mengapa berhenti pada satu argumen? Membungkus kode ke dalam loop for(;*argp!=NULL;++argp)benar-benar tidak ada usaha sama sekali, menambahkan paling banyak beberapa instruksi mesin ke biner, dan menghindari keharusan mengeluh tentang sejumlah argumen yang salah (yang menyimpan lebih banyak instruksi). Merusak versi primitif dari cat, menyatukan file. (Sejujurnya Anda perlu men-tweak sedikit sehingga tanpa argumen berperilaku seperti itu null.)

Tentu saja dalam catprogram yang sebenarnya , mereka menambahkan beberapa lonceng dan peluit, karena mereka selalu melakukannya. Tetapi intinya adalah bahwa aspek "gabungan" dari catbiaya benar-benar tidak ada usaha sama sekali, baik untuk programmer maupun untuk mesin yang mengeksekusinya. Fakta yang catmerangkum nulldan nocatmenjelaskan tidak adanya program tersebut. Hindari menggunakan catdengan argumen tunggal jika hasilnya masuk ke jalur pipa, tetapi jika itu digunakan hanya untuk menampilkan konten file di terminal, bahkan halaman yang saya tautkan untuk mengakui bahwa ini adalah penggunaan yang bermanfaat cat, jadi jangan ragu.


Anda dapat menguji yang catbenar-benar diimplementasikan oleh loop sederhana di sekitar nocatfungsi hypthetical , dengan memanggil catdengan beberapa nama file yang salah satu nama tidak valid, bukan pada posisi pertama: daripada mengeluh segera bahwa file ini tidak ada, catpertama-tama dump terlebih dahulu sebelumnya file yang valid, dan kemudian mengeluh tentang file yang tidak valid (setidaknya itulah perilaku kucing saya).


7

Sedang zshdicoba

<file

Saya percaya ini adalah cara terpendek untuk mencetak file. Ini menggunakan 'tersembunyi' cat(atau morejika stdout adalah terminal), tetapi perintah yang digunakan untuk pencetakan dikendalikan oleh READNULLCMDvariabel yang Anda dapat dengan aman menimpa langsung dengan nama perintah atau bahkan oleh beberapa fungsi. Misalnya untuk mencetak file dengan penomoran baris:

numcat() { nl -s'> ' -w2 - }
READNULLCMD=numcat
<file

5

POSIX mendefinisikan cat sebagai:

NAMA

cat - menyatukan dan mencetak file

RINGKASAN

cat [-u] [file ...]

DESKRIPSI

Utilitas cat harus membaca file secara berurutan dan akan menulis kontennya ke output standar dalam urutan yang sama.

Jadi saya pikir menggabungkan di sini berarti membaca file secara berurutan .


5

Saya tahu ini pertanyaan masa lalu. Secara teknis, karena mencetak isi suatu file stdoutadalah bentuk gabungan, catsecara semantik sesuai. Jangan lupa bahwa printfsecara semantik dimaksudkan untuk memformat dan mencetak data. Bash juga menyediakan sintaks untuk mengarahkan input dan output dari file. Kombinasi ini dapat menghasilkan ini:

printf '%s' "$(<file.txt)"

4
Selain secara khusus bundaran, perintah yang ditampilkan tidak sama dengan cat file.txt, karena perintah itu akan menghapus baris baru yang tertinggal (yang $(...)melakukan ini).
Marc van Leeuwen

+1, tangkapan yang bagus. Tidak tahu itu.
James M. Lay

3

Menggunakan bashbawaan dan menghindari pembuatan subproses:

{ while IFS='' read -rd '' _bcat_; do printf '%s\0' "${_bcat_}"; done; printf '%s' "${_bcat_}"; unset _bcat_; } <'/path/to/file'

IFShanya akan diterapkan pada readperintah, jadi jangan khawatir tentang IFSperubahan global Anda .

Diperlukan loop untuk menangani karakter nol (terima kasih kepada Stéphane Chazelas).

Cara ini tidak cocok untuk file besar karena konten file membaca variabel (jadi memori) terlebih dahulu. BTW Saya sudah mencoba untuk mencetak file teks 39M dengan cara ini dan penggunaan memori bash tidak melebihi 5M, jadi tidak yakin tentang kasus ini.

Ini juga sangat lambat dan CPU tidak efisien: untuk file 39M yang sama butuh ~ 3 menit dengan 100% penggunaan single core.

Untuk file besar atau binari lebih baik digunakan cat '/path/to/file'atau bahkan dd if='/path/to/file' bs=1Mjika memungkinkan.


1
Lihat juga pv -qyang di Linux dapat digunakan splice()yang untuk beberapa jenis stdin / stdout akan meningkatkan kinerja.
Stéphane Chazelas

1

Sama seperti demonstrasi, Anda bisa melakukannya

cp foo /dev/stdout
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.