ตัวอธิบายไฟล์ & เชลล์สคริปต์


32

ฉันมีเวลายากมากที่จะเข้าใจว่าคน ๆ หนึ่งใช้ file descriptor ใน shell script ได้อย่างไร

ฉันรู้พื้นฐานเช่น

exec 5 > /tmp/foo

ดังนั้น fd 5 จะแนบกับ foo เพื่อเขียน

exec 6 < /tmp/bar

…สำหรับการอ่าน

exec 5>&-

…ปิด fd

ตอนนี้จะทำอะไร?

#!/bin/bash

exec 5 > /tmp/foo 
exec 6 < /tmp/bar 

cat <&6 | while read a
do
     echo $a >&5
done

ตามที่ฉันเข้าใจ&5ปิด fd แล้วเอาต์พุตยังคงถูกจัดทิศทางใหม่ได้สำเร็จหลังจากการโทรแต่ละครั้งอย่างไร

นี่คือสำเนาพาสต้าจาก: ที่นี่

มันอ้างว่าการใช้สิ่งนี้อย่างง่ายecho $a > fileจะทำให้เร็วขึ้น แต่ฉันก็ไม่เข้าใจ ฉันขอขอบคุณลิงก์ใด ๆ เพื่อการสอนที่ดี ฉันพลัง google ดูเหมือนจะล้มเหลวฉัน

คำตอบ:


44

ขั้นแรกให้สังเกตว่าไวยากรณ์สำหรับการปิดคือ5>&-หรือ6<&-ขึ้นอยู่กับว่าไฟล์ descriptor กำลังอ่านเพื่อการเขียนหรือสำหรับการอ่าน ดูเหมือนว่ามีการพิมพ์ผิดหรือการจัดรูปแบบความผิดพลาดในบล็อกโพสต์นั้น

นี่คือสคริปต์ที่แสดงความคิดเห็น

exec 5>/tmp/foo       # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar       # open /tmp/bar for reading, on fd 6
cat <&6 |             # call cat, with its standard input connected to
                      # what is currently fd 6, i.e., /tmp/bar
while read a; do      # 
  echo $a >&5         # write to fd 5, i.e., /tmp/foo
done                  # 

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

cat </tmp/bar |
while read a; do
  echo $a
done >/tmp/foo

การใช้ตัวอธิบายไฟล์อย่างชัดเจนจะมีประโยชน์เมื่อคุณต้องการเขียนไปยังหลาย ๆ ไฟล์ ตัวอย่างเช่นพิจารณาสคริปต์ที่เอาต์พุตข้อมูลไปยังไฟล์เอาต์พุตข้อมูลและข้อมูลการบันทึกไปยังล็อกไฟล์และอาจมีข้อความแสดงข้อผิดพลาดเช่นกัน นั่นหมายถึงช่องสัญญาณออกสามช่อง: ช่องหนึ่งสำหรับข้อมูลช่องหนึ่งสำหรับบันทึกและอีกช่องสำหรับข้อผิดพลาด เนื่องจากมีเพียงสอง descriptor มาตรฐานสำหรับเอาต์พุตจึงจำเป็นต้องใช้ตัวที่สาม คุณสามารถเรียกexecเพื่อเปิดไฟล์เอาต์พุต:

exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3

if something_bad_happens; then echo error message >&2; fi
exec >&-  # close the data output file
echo "output file closed" >&3

หมายเหตุเกี่ยวกับประสิทธิภาพเกิดขึ้นเมื่อคุณมีการเปลี่ยนเส้นทางในลูปเช่นนี้ (ถือว่าไฟล์ว่างเปล่าเพื่อเริ่มต้นด้วย):

while …; do echo $a >>/tmp/bar; done

ในการวนซ้ำแต่ละครั้งโปรแกรมจะเปิดขึ้น/tmp/barเพื่อค้นหาที่ส่วนท้ายของไฟล์ผนวกข้อมูลบางส่วนและปิดไฟล์ มันจะมีประสิทธิภาพมากขึ้นในการเปิดไฟล์ทันที:

while …; do echo $a; done >/tmp/bar

เมื่อมีการเปลี่ยนเส้นทางหลายครั้งเกิดขึ้นในช่วงเวลาที่แตกต่างกันการโทรexecเพื่อทำการเปลี่ยนเส้นทางมากกว่าการปิดกั้นบล็อกในการเปลี่ยนเส้นทางจะมีประโยชน์

exec >/tmp/bar
while …; do echo $a; done

คุณจะพบตัวอย่างio-redirectionอื่น ๆของการเปลี่ยนเส้นทางโดยเรียกดูแท็กในไซต์นี้


1
ทั้งไวยากรณ์สำหรับการปิดไฟล์ descriptor นั้นทำสิ่งเดียวกัน
user1338062
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.