อะไรคือ <() ใน bash (และ = () ใน zsh)?


36

ฉันค่อนข้างสบายใจกับทุบตี แต่เมื่อเร็ว ๆ นี้ฉันลงเอยด้วยการเปลี่ยนตัวที่ฉันไม่รู้

<(<command>)ทุบตีอะไรกันแน่? มันเปรียบเทียบกับ=(<command>)in zsh อย่างไร

ฉันเข้าใจว่าสิ่งนี้เกี่ยวข้องกับตัวอธิบายไฟล์เริ่มต้น ในคอมพิวเตอร์ของฉัน

echo <()

กลับ/proc/self/fd/11มาซึ่งฉันพบว่าเป็นสำเนาของสคริปต์ STDOUT แต่นี่ก็ดูค่อนข้างสับสนสำหรับฉัน

คำตอบ:


51

สิ่งนี้เรียกว่าการทดแทนกระบวนการ

<(list)ไวยากรณ์การสนับสนุนจากทั้งสองและbash zshมันมีวิธีการส่งออกของคำสั่ง ( list) ไปยังคำสั่งอื่นเมื่อใช้ไปป์ ( |) เป็นไปไม่ได้ ตัวอย่างเช่นเมื่อคำสั่งไม่สนับสนุนอินพุตSTDINหรือคุณต้องการเอาต์พุตของหลายคำสั่ง:

diff <(ls dirA) <(ls dirB)

<(list)เชื่อมต่อเอาต์พุตของlistกับไฟล์/dev/fdหากระบบได้รับการสนับสนุนมิฉะนั้นจะใช้ชื่อไปป์ (FIFO) (ซึ่งยังขึ้นอยู่กับการสนับสนุนของระบบด้วยตนเองไม่มีคู่มือบอกว่าเกิดอะไรขึ้นถ้ากลไกทั้งสองไม่ได้รับการสนับสนุน ข้อผิดพลาด) ชื่อของไฟล์นั้นจะถูกส่งผ่านเป็นอาร์กิวเมนต์ในบรรทัดคำสั่ง


zshนอกจากนี้ยังสนับสนุนการแทนเป็นไปได้สำหรับ=(list) <(list)ด้วย=(list)ไฟล์ชั่วคราวจะใช้แทนไฟล์ใน/dev/fdหรือ FIFO มันสามารถใช้แทน<(list)หากโปรแกรมต้องดูในผลลัพธ์

ตามคู่มือ ZSHอาจมีปัญหาอื่น ๆ เกี่ยวกับวิธีการ<(list)ทำงาน:

=รูปแบบจะเป็นประโยชน์ทั้งสอง/dev/fdและการดำเนินงานท่อที่มีชื่อของ<(...)มีข้อบกพร่อง ในกรณีก่อนหน้าบางโปรแกรมอาจปิดตัวอธิบายไฟล์ที่เป็นปัญหาโดยอัตโนมัติก่อนที่จะตรวจสอบไฟล์ในบรรทัดคำสั่งโดยเฉพาะในกรณีที่จำเป็นสำหรับเหตุผลด้านความปลอดภัยเช่นเมื่อโปรแกรมกำลังทำงาน setuid ในกรณีที่สองหากโปรแกรมไม่ได้เปิดไฟล์จริง subshell ที่พยายามจะอ่านหรือเขียนไปที่ไปป์ไลน์จะ (ในการใช้งานทั่วไประบบปฏิบัติการที่แตกต่างกันอาจมีพฤติกรรมที่แตกต่างกัน) และจะต้องถูกฆ่าอย่างชัดเจน . ในทั้งสองกรณีเชลล์จะส่งข้อมูลโดยใช้ไพพ์เพื่อให้โปรแกรมที่คาดว่าจะ lseek (ดู man page lseek(2)) บนไฟล์ไม่ทำงาน


สิ่งนี้ช่วยให้ฉันทราบว่าทำไม MacOS ถึงpfctl -f <(echo "pf rules")พูดตัวอธิบายไฟล์ไม่ดี ใช้ zsh และ = (echo "pf rules") แทนใช้งานได้
johnnyB

9

หมายเหตุนี่คือคำตอบ bash ไม่ใช่ zsh

มีหลายกรณีที่ทุบตีซึ่งคุณไม่สามารถใช้ไพพ์ได้:

some_command | some_other_command

เนื่องจากท่อแนะนำ subshells สำหรับแต่ละองค์ประกอบของไปป์ไลน์เมื่อ subshells ออกผลข้างเคียงใด ๆ ที่คุณพึ่งพาจะหายไป ตัวอย่างเช่นตัวอย่างที่วางแผนไว้นี้:

cat file | while read line; do ((count++)); done
echo $count

จะแสดงบรรทัดว่างเนื่องจาก$countตัวแปรไม่มีอยู่ในเชลล์ปัจจุบัน

การทดแทนกระบวนการทุบตีช่วยให้คุณหลีกเลี่ยงปริศนานี้โดยอนุญาตให้คุณอ่านจากเอาต์พุต "some_command" ตามที่คุณต้องการจากไฟล์

while read line; do ((count++)); done < <(cat file)
# ....................................1.2
echo $count   # the variable *does* exist in the current shell

(1) เป็นการเปลี่ยนเส้นทางอินพุตปกติ (2) เป็นการเริ่มต้นของ<()ไวยากรณ์การแทนที่กระบวนการ


2
= (cmdlist) ใน zsh เกือบจะมีผลเช่นเดียวกับ <(cmdlist) ใน bash แต่จะสร้าง (และลบเมื่อพร้อม) ไฟล์ชั่วคราวที่มีเอาต์พุตของ cmdlist สำหรับการเปลี่ยนเส้นทาง สิ่งนี้เป็นสิ่งที่ดีเมื่อค้นหาอาจเกิดขึ้นในโปรแกรม <(cmdlist) เป็นที่รู้จักกันโดย zsh เช่นกัน
Gombai Sándor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.