เหตุใดจึงมี / bin / echo และทำไมฉันต้องการใช้


52

ฉันสังเกตเห็นว่ามีระบบปฏิบัติการไบนารี/bin/echoบน Ubuntu MATE 17.04 ของฉัน

ฉันคิดว่ามันแปลกเพราะ

$ type echo
echo is a shell builtin

การทดสอบแบบคร่าวๆแสดงให้เห็นว่า/bin/echoสิ่งเดียวกันกับ Bash builtin echo:

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

เหตุใดจึงมีรุ่นอื่นechoแยกต่างหากจากโปรแกรม Bash และเพราะเหตุใดหรือเมื่อใดฉันจึงต้องการใช้


10
การสนทนา - unix.stackexchange.com/questions/1355/…
Panther

2
@ bodhi.zazen มันค่อนข้างมีประโยชน์แม้ว่ามันจะไม่เหมือนกันเพราะมันพูดถึงการสนทนาของคำถามนี้ คำถามนั้นถามว่าทำไมechoถูกจัดให้เป็นเชลล์บิวด์อินในขณะที่คำถามนี้ถามว่าทำไมมันถูกจัดเตรียมไว้เป็นคำสั่งภายนอก
Eliah Kagan

3
เหตุผลหนึ่งคือไม่ใช่ทุกคนที่ใช้ทุบตี ฉันเดาว่า / bin / echo มีการทุบตีและผู้พัฒนาพบว่ามีประโยชน์ / มีประสิทธิภาพในการรวมเป็นบิวด์อินแทนที่จะใช้ไฟล์ปฏิบัติการ
jamesqf

คำตอบ:


88

ถ้าคุณเปิดขึ้นbashรวดเร็วและประเภทในechoคำสั่งที่ใช้เปลือก builtin/bin/echoมากกว่าทำงาน เหตุผลที่ยังคงมีความสำคัญสำหรับ/bin/echoการมีอยู่คือ:

  1. คุณไม่ได้ใช้เชลล์เสมอไป ภายใต้สถานการณ์ที่หลากหลายคุณสามารถรันโปรแกรมที่รันได้โดยตรงและไม่ผ่านเชลล์
  2. อย่างน้อยในทางทฤษฎีแล้วเปลือกหอยบางอันไม่มีechoตัวต่อ สิ่งนี้ไม่จำเป็นจริง ๆ

เพื่อขยาย # 1 สมมติว่าคุณต้องการที่จะย้ายทุกไฟล์ปกติที่มีชื่อเริ่มต้นด้วยabcทุกที่ในการsrc destมีหลายวิธีที่จะทำเช่นนั้น แต่หนึ่งในนั้นคือ:

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

แต่สมมติว่าแทนที่จะเรียกใช้สิ่งนั้นคุณต้องการเห็นทุกคำสั่งที่จะทำงานก่อน ถ้าอย่างนั้นคุณสามารถผนวกechoคำสั่งไว้ได้เช่นเดียวกับในบริบทอื่น ๆ :

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

แต่findไม่ได้ใช้เปลือก /bin/echoที่ทำงาน

นอกจากนี้findมี-execหรือ-execdirที่/bin/echoปฏิบัติการจะถูกเรียกโดยโปรแกรมอื่น ๆ ที่ตัวเองเรียกใช้โปรแกรม แต่ไม่ผ่านเปลือก นี้เกิดขึ้นกับxargsคำสั่ง (ซึ่งเป็นเรื่องที่เกี่ยวข้องไปfind) เช่นเดียวกับในหลายบริบทอื่น ๆ เช่นบรรทัดของไฟล์ อีกตัวอย่างหนึ่งคือเมื่อคุณเรียกใช้ซึ่งจะเป็นประโยชน์สำหรับการทดสอบว่าทำงานหรือไม่Exec=.desktopsudo echosudo

ในทำนองเดียวกันเชลล์บางตัวมีprintfbuiltin แต่/usr/bin/printfมีอยู่ด้วย

สาเหตุที่เป็นไปได้น้อยที่คุณอาจใช้โดยเจตนา/bin/echoคือถ้าคุณพึ่งพาความแตกต่างระหว่างมันและechoคำสั่งที่เชลล์จัดเตรียมไว้ให้ man echoเอกสาร/bin/echo; help echoใน bashเอกสารbashบิวด์อิน echoไม่ได้เป็นแบบพกพามากเพราะการใช้งานที่แตกต่างกัน - ทั้งในระบบปฏิบัติการและทั่วเปลือกหอยในปฏิบัติการเดียวกัน system-- สนับสนุนตัวเลือกที่แตกต่างกัน (เช่น-e) และแตกต่างกันในการรักษาของพวกเขาทับขวา แน่นอนว่าควรหลีกเลี่ยงการใช้รายละเอียดดังกล่าวและใช้printfแทนซึ่งพกพาสะดวกกว่า

ในbashคุณสามารถสร้างtypeบิวด์อินได้/bin/echoเช่นกันโดยสมมติว่า/binมันเป็นของคุณ$PATHอย่างที่ควรจะเป็นโดยการส่ง-aแฟล็ก :

$ type -a echo
echo is a shell builtin
echo is /bin/echo

21
และเนื่องจากข้อกำหนด POSIXบอกว่าจะต้องมีอย่างใดอย่างหนึ่ง
เกล็นแจ็คแมน

4
@glennjackman ฉันหวังว่าจะมีคนโพสต์คำตอบเกี่ยวกับเรื่องนั้นจริง ๆ และฉันหวังว่าคุณจะตัดสินใจทำเช่นนั้น! มีความละเอียดอ่อนที่เกี่ยวข้องบางส่วน แต่เป็นเป็นไม่ Debian, Ubuntu หรือ GNU coreutils (หรือโครงการ GNU รวมทั้งหมด) พยายามที่จะสอดคล้องกับ POSIX ในทุกอย่าง ตัวอย่างเช่นPOSIX ยืนยันการcdปฏิบัติการอยู่ (ซึ่งเมื่อเรียกใช้การเปลี่ยนแปลงไดเรกทอรีและออกจากผู้โทรที่พวกเขาก่อน) และระบบปฏิบัติการบางคนมีหนึ่ง มันอาจจะเป็นประโยชน์ในการอ้างอิง4.1 ในมาตรฐาน
Eliah Kagan

@EliahKagan: Incidentaly / usr / bin / cd มีการใช้งาน: คำสั่งไดเร็กทอรี / usr / bin / cd รันคำสั่งนั้นในไดเรกทอรีนั้น หากการเปลี่ยนไดเรกทอรีล้มเหลวคำสั่งจะไม่เริ่มขึ้น
Joshua

4
@Joshua การใช้งานที่ดีขึ้นcdเป็นเพียงการทดสอบความสามารถในการเข้าถึงไดเรกทอรีที่กำหนด: หาก/usr/bin/cd some/dirประสบความสำเร็จในการถ่ายภาพหนึ่งครั้งคุณได้ทดสอบ: a) ที่some/dirมีอยู่ b) เป็นไดเรกทอรีหรือลิงก์ไปยังไดเรกทอรีหนึ่งและ c) สิทธิ์ที่จำเป็นสำหรับคุณในการเข้าถึงไดเรกทอรีนั้นมีอยู่; ทั้งหมดโดยไม่เปลี่ยนสถานะของคุณเอง
muru

1
@CarlWitthoft ให้ดูที่เหตุใด printf จึงดีกว่า echo นอกจากนี้ยัง/bin/echoไม่ใช่\bin\echoยกเว้นว่าคุณใช้ Windows ;)
Wildcard

31

Eliah ทำหน้าที่ได้ยอดเยี่ยมในการตอบคำถามนี้ แต่ฉันต้องการแสดงความคิดเห็นเกี่ยวกับส่วน "ทำไมจึงมีเวอร์ชั่นechoแยกต่างหากจากโปรแกรม Bash" นั่นเป็นคำถามที่ผิด

คำถามที่ถูกต้องคือ: ทำไมนี่คือ builtin ในสถานที่แรกเมื่อมันอาจจะเป็น (และเป็น) คำสั่งภายนอกที่ดีอย่างสมบูรณ์?

เพื่อความเรียบง่ายลองดูบิวด์อินในเส้นประที่ 38 อย่างน่ากลัว (bash มี 61 เพื่อเปรียบเทียบโดยไปที่เอาท์พุต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

ต้องสร้างสิ่งเหล่านี้กี่ตัว? [, echo, false, printf, pwd, testและtrueไม่ต้องการที่จะเป็น builtins: พวกเขาไม่ได้ทำอะไรที่เฉพาะในตัวสามารถทำ (หรือได้รับผลกระทบต่อรัฐเปลือกที่ไม่สามารถใช้ได้กับคำสั่งภายนอก) ทุบตีของprintfอย่างน้อยจะได้ประโยชน์จากการเป็น builtin: การบันทึกการส่งออกให้กับตัวแปรprintf -v var ใน bash ก็มีความพิเศษด้วยการเป็นคีย์เวิร์ดคุณสามารถใช้เวลาในรายการคำสั่งโดยพลการใน bash (เส้นประไม่ได้เทียบเท่า) ไม่จำเป็นต้องเป็นบิวด์อิน - คำสั่งภายนอกใด ๆ จะสืบทอดไดเรกทอรีทำงานปัจจุบัน (และเป็นคำสั่งภายนอกด้วย)vartimetimepwd:เป็นข้อยกเว้น - คุณต้องมี NOP และ:เป็น ส่วนที่เหลือทำการกระทำที่คำสั่งภายนอกสามารถทำได้อย่างง่ายดาย

ดังนั้นหนึ่งในห้าของสิ่งปลูกสร้างเหล่านี้จึงไม่จำเป็นต้องเป็นตัวสร้าง แล้วทำไม? manpage * จริงอธิบายในการผ่านเหตุผลเหล่านี้เป็น builtins (เหมืองเน้น):dash

builtins
 ส่วนนี้แสดงรายการคำสั่ง builtin ซึ่งสร้างขึ้นเพราะ
 จำเป็นต้องดำเนินการบางอย่างที่แยกไม่ได้
 กระบวนการ. นอกจากนี้ยังมีคำสั่งอื่น ๆ อีกหลายอย่างที่อาจมี
 สร้างขึ้นเพื่อประสิทธิภาพ (เช่น printf (1), echo (1), ทดสอบ (1), ฯลฯ )

นั่นเป็นสิ่งที่ค่อนข้างมาก: สิ่งเหล่านี้มีอยู่ภายในเพราะมีการใช้บ่อยครั้งมีการโต้ตอบและในสคริปต์และการทำงานของพวกเขานั้นง่ายพอที่เชลล์สามารถทำงานได้ และเพื่อให้มันเกิดขึ้น: บางคน (ส่วนใหญ่) เปลือกหอยเอาในงาน ** กลับไป. จาก2.9 BSDและคุณจะไม่พบในตัวshecho

ดังนั้นมันเป็นไปได้โดยสิ้นเชิงที่เชลล์ขนาดเล็กสามารถข้ามการใช้คำสั่งเช่นบิวด์อิน (ฉันไม่คิดว่าเชลล์ปัจจุบันใดจะทำได้) โครงการ coreutils ของ GNU ไม่คิดว่าคุณจะใช้มันในเชลล์ตัวใดตัวหนึ่งและ POSIX ต้องการคำสั่งเหล่านี้ ดังนั้น coreutils ให้สิ่งเหล่านี้แล้วและข้ามสิ่งที่ไม่มีความหมายใด ๆ นอกเหนือจากเปลือก


* นี่เกือบจะเหมือนกับข้อความ manpage ที่สอดคล้องกันสำหรับ Almquist shellซึ่งเป็นเส้นประที่เชลล์ Debian Almquist ใช้

** zshใช้ความคิดนี้ไปมาก: คำสั่งที่คุณจะได้รับโดยการโหลดโมดูลต่างๆเช่นzmv, เป็นสิ่งที่คุณจะไม่คิดว่าเปลือกจำเป็นต้องได้รับเข้าไป ณ จุดนี้คำถามที่แท้จริงคือทำไมคุณจะใช้ทุบตีแทน zsh ซึ่งมี builtins เหล่านี้ทั้งหมด


1
ปรากฎว่า: ไม่จำเป็นต้องเป็นตัวภายใน มันเป็นเรื่องโง่เขลาที่จะไม่เป็นคนในตัว เว้นแต่คุณจะจัดการกับปัญหาระดับต้นของฟลอปปี้ดิสก์ระดับกู้ภัย (ซึ่งในกรณีนี้ฉันค้นพบวิธีที่ยากในการที่ pwd ใช้งานไม่ได้อย่างน่าเชื่อถือเช่นกัน) การลงโทษเพียงอย่างเดียวสำหรับการไม่มีสิ่งนี้
Joshua

5
@ โจชัวไม่:เนื่องจากภายนอกไม่ได้เป็น NOP จริงๆคุณยังคงมีการPATHค้นหาความพยายามในการดำเนินการคำสั่ง ฯลฯ เมื่อสิ่งที่คุณต้องการคือการไม่ทำอะไรเลย :ในขณะที่ builtin ทำอย่างนั้น
muru

2
จริง ๆ แล้วทุบตีไม่จำเป็นต้องpwdมีในตัวเพื่อให้มันทำงานอย่างที่มันทำกับพฤติกรรมเริ่มต้นของการแสดงเส้นทาง "ตรรกะ" ( pwd -L) /bin/pwdสามารถใช้pwd -Pพฤติกรรมการแสดงไดเรกทอรีหลักที่แท้จริงให้กับคุณเท่านั้นไม่ใช่ symlink ที่คุณcdแก้ไข
Peter Cordes

2
@PeterCordes pwdสถานะ 's เป็นบิตที่ถูกบุกรุกโดยการแสดงตนของPWDแต่ใช่ว่านอกจากนี้ยังเป็นตัวอย่างของการทุบตีใช้สถานะ builtin เพื่อปรับปรุงการทำงาน
Muru
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.