Mengapa ada / bin / echo dan mengapa saya ingin menggunakannya?

52

Saya perhatikan bahwa ada biner yang dapat dieksekusi /bin/echopada sistem Ubuntu MATE 17.04 saya.

Saya pikir, itu aneh, karena

$ type echo
echo is a shell builtin

Pengujian sepintas menunjukkan bahwa /bin/echomelakukan hal yang sama seperti Bash builtin echo:

$ /bin/echo foo
foo
$ /bin/echo $USER
zanna

Jadi, mengapa ada versi lain yang echoterpisah dari program Bash, dan mengapa atau kapan saya ingin menggunakannya?

Zanna
sumber
2
@ bodhi.zazen Itu cukup berguna walaupun tidak sama, karena membahas kebalikan dari pertanyaan ini. Pertanyaan itu menanyakan mengapa echodisediakan sebagai shell builtin, sementara yang ini bertanya mengapa disediakan sebagai perintah eksternal.
Eliah Kagan
3
Salah satu alasannya adalah tidak semua orang menggunakan bash. Saya kira / bin / echo lebih dulu dari bash, dan para pengembang merasa berguna / efisien untuk memasukkannya sebagai built-in daripada menggunakan executable.
jamesqf

Jawaban:

87

Jika Anda membuka bashprompt dan mengetikkan echoperintah, yang menggunakan shell builtin daripada menjalankan /bin/echo. Alasan yang masih penting untuk tetap /bin/echoada adalah:

  1. Anda tidak selalu menggunakan shell. Dalam berbagai keadaan, Anda menjalankan executable secara langsung dan tidak melalui shell.
  2. Setidaknya secara teori, beberapa kerang tidak memiliki echobuiltin. Ini sebenarnya tidak diperlukan.

Untuk memperluas pada # 1, misalkan Anda ingin memindahkan semua file biasa yang namanya mulai dari abcmana saja srcke dest. Ada beberapa cara untuk melakukan itu tetapi salah satunya adalah:

find src -name 'abc*' -type f -exec mv -nv {} dest/ \;

Tapi misalkan, daripada hanya menjalankannya, Anda ingin melihat setiap perintah yang akan dijalankan terlebih dahulu. Nah, maka Anda bisa menambahkan echoke perintah, sama seperti Anda dalam konteks lain:

find src -name 'abc*' -type f -exec echo mv -nv {} dest/ \;

Tetapi findtidak menggunakan shell. Itu berjalan /bin/echo.

Selain finddengan -execatau-execdir , /bin/echoexecutable akan dipanggil oleh program lain yang menjalankan program sendiri tetapi tidak melalui shell. Ini terjadi dengan xargsperintah (yang berkaitan dengan find), serta di sejumlah konteks lain, seperti yang Exec=baris dari sebuah .desktopfile yang . Contoh lain adalah ketika Anda menjalankan sudo echo, yang dapat berguna untuk pengujian jika sudoberfungsi.

Demikian pula, beberapa kerang memiliki printfbuiltin tetapi /usr/bin/printfjuga ada.

Alasan yang kurang umum yang mungkin Anda sengaja gunakan /bin/echoadalah jika Anda mengandalkan perbedaan antara itu dan echoperintah yang diberikan oleh shell Anda. man echodokumen /bin/echo; help echodalam bash dokumen bashbawaan. echotidak terlalu portabel, karena implementasi yang berbeda - baik lintas sistem operasi maupun lintas shell pada sistem operasi yang sama - mendukung opsi yang berbeda (misalnya, -e) dan berbeda dalam perawatan backslash . Tentu saja, lebih baik untuk tidak mengandalkan detail seperti itu, dan menggunakannya printfsebagai gantinya, yang jauh lebih portabel .

Di bash, Anda dapat membuat typepertunjukan bawaan /bin/echojuga - dengan asumsi /binada di dalam Anda $PATHsebagaimana mestinya - dengan mengedarkannya -aflag :

$ type -a echo
echo is a shell builtin
echo is /bin/echo
Eliah Kagan
sumber
21
Dan juga karena spesifikasi POSIX mengatakan harus ada satu.
glenn jackman
4
@glennjackman Saya berharap seseorang akan mengirim jawaban tentang itu, sebenarnya, dan saya harap Anda memutuskan untuk melakukannya! Ada beberapa kehalusan yang terlibat, karena baik Debian, Ubuntu, maupun GNU Coreutils (maupun keseluruhan Proyek GNU) mencoba untuk mematuhi POSIX dalam segala hal . Sebagai contoh, POSIX menegaskan cdada yang dapat dieksekusi (yang, ketika dijalankan, mengubah direktori dan berhenti, meninggalkan pemanggil di mana mereka sebelumnya) dan beberapa OS memilikinya. Mungkin bermanfaat untuk mengutip 4.1 dalam standar GNU .
Eliah Kagan
@EliahKagan: Insiden / usr / bin / cd telah menggunakan: / usr / bin / cd direktori perintah menjalankan perintah itu di direktori itu. Jika perubahan direktori gagal, perintah tidak dimulai.
Joshua
4
@Joshua, penggunaan yang lebih baik cdhanyalah sebagai tes kemampuan untuk mengakses direktori yang diberikan: jika /usr/bin/cd some/dirberhasil, dalam satu kesempatan Anda telah menguji: a) yang some/dirada, b) bahwa itu adalah direktori atau tautan ke satu, dan c) izin yang diperlukan bagi Anda untuk mengakses direktori yang ada; semua tanpa mengubah kondisi Anda sendiri.
muru
1
@CarlWitthoft, lihat Mengapa printf lebih baik daripada gema? Juga /bin/echo, tidak \bin\echo, kecuali jika Anda menggunakan Windows. ;)
Wildcard
31

Eliah melakukan pekerjaan yang bagus untuk menjawab ini, tetapi saya ingin berkomentar tentang bagian "mengapa ada versi lain yang echoterpisah dari program Bash". Itu pertanyaan yang salah.

Pertanyaan yang tepat adalah: mengapa ini dibangun di tempat pertama , padahal bisa saja (dan) merupakan perintah eksternal yang baik-baik saja?

Untuk kesederhanaan, lihat builtin di dash, 38 sangat sedikit (bash memiliki 61, untuk perbandingan, pergi dengan output dari compgen -b):

.               continue        getopts         readonly        type
:               echo            hash            return          ulimit
[               eval            jobs            set             umask
alias           exec            kill            shift           unalias
bg              exit            local           test            unset
break           export          printf          times           wait
cd              false           pwd             trap
command         fg              read            true

Berapa banyak dari ini yang harus dibangun? [, echo, false, printf, pwd, test, Dan truetidak perlu menjadi builtin: Mereka tidak melakukan apa pun yang hanya builtin dapat melakukan (mempengaruhi atau mendapatkan negara shell yang tidak tersedia untuk perintah eksternal). Bash printfsetidaknya mengambil keuntungan sebagai builtin: printf -v varmenyimpan output ke variabel var. timedi bash juga istimewa: dengan menjadi kata kunci, Anda dapat mengatur waktu daftar perintah arbitrer di bash (tanda hubung tidak memiliki yang timesetara). pwdtidak perlu menjadi builtin juga - perintah eksternal apa pun akan mewarisi direktori kerja saat ini (dan itu juga perintah eksternal ).:adalah pengecualian - Anda memerlukan NOP, dan :apakah itu. Sisanya melakukan tindakan yang dapat dilakukan dengan mudah oleh perintah eksternal.

Jadi, seperlima dari builtin ini tidak perlu builtin. Lalu mengapa? Halaman dashmanual * sebenarnya menjelaskan secara sepintas mengapa ini adalah bawaan (penekanan milikku):

Dibangun
 Bagian ini mencantumkan perintah builtin yang dibangun karena mereka
 perlu melakukan beberapa operasi yang tidak dapat dilakukan oleh yang terpisah
 proses. Selain itu, ada beberapa perintah lain yang mungkin
 dibangun untuk efisiensi (misalnya printf (1), echo (1), test (1), dll).

Cukup banyak: bawaan ini ada karena sering digunakan, secara interaktif dan dalam skrip, dan fungsinya cukup sederhana, sehingga shell dapat melakukan pekerjaannya. Dan itu terjadi: beberapa (? Kebanyakan) kerang mengambil pekerjaan ** Kembali ke. Yangsh dari 2,9 BSD , dan Anda tidak akan menemukan echobuiltin.

Jadi, sangat mungkin shell minimal dapat melewati implementasi perintah seperti builtin (saya pikir shell saat ini tidak melakukannya). Proyek GNU coreutils tidak berasumsi bahwa Anda akan menjalankannya dalam shell tertentu, dan POSIX membutuhkan perintah ini. Jadi, coreutils menyediakan ini, dan melewatkan yang tidak memiliki makna di luar shell.


* Ini hampir identik dengan teks halaman manual yang sesuai untuk shell Almquist , yang menjadi dasar dasbor itu, shell Debian Almquist, didasarkan.

** zshmembawa ide ini ke ekstrem: perintah yang Anda dapatkan dengan memuat berbagai modul, seperti zmv, adalah hal-hal yang Anda pikir tidak perlu dimasukkan ke dalam shell . Pada titik itu, pertanyaan sebenarnya adalah: mengapa Anda menggunakan bash alih-alih zsh, yang memiliki semua bawaan ini?

muru
sumber
1
Ternyata: tidak perlu dibangun juga. Ini konyol untuk tidak menjadi builtin. Kecuali jika Anda berurusan dengan masalah tingkat penyelamatan-floppy init awal (dalam hal ini saya menemukan cara yang sulit pwd tidak bekerja dengan baik baik) satu-satunya hukuman karena tidak memiliki ini sebagai builtin adalah kinerja yang mengerikan.
Joshua
5
@Joshua tidak, :sebagai eksternal tidak akan benar-benar menjadi NOP, Anda masih harus PATHmencari, upaya untuk mengeksekusi perintah, dll, ketika semua yang Anda inginkan adalah secara tegas tidak melakukan apa-apa. :sebagai builtin melakukan itu.
muru
2
Bash sebenarnya perlu pwdbuilt-in untuk bisa bekerja seperti itu, dengan perilaku default menunjukkan jalur "logis" ( pwd -L). /bin/pwdhanya bisa menerapkan pwd -Pperilaku menunjukkan kepada Anda direktori induk yang sebenarnya, bukan symlink yang Anda cdlalui.
Peter Cordes
2
Status @PeterCordes pwdsedikit terganggu oleh kehadiran PWD, tetapi ya, itu juga merupakan contoh bash menggunakan status
bawaan