คำถามของฉันเกี่ยวกับการเปลี่ยนเส้นทางที่สำคัญคือทุบตี สมมติว่าคุณมีคำสั่ง:
cmd1 < cmd2 > cmd3
มันจะแปลเป็น:
(cmd1 < cmd2) > cmd3
หรือ
cmd1 < (cmd2 > cmd3)
คำถามของฉันเกี่ยวกับการเปลี่ยนเส้นทางที่สำคัญคือทุบตี สมมติว่าคุณมีคำสั่ง:
cmd1 < cmd2 > cmd3
มันจะแปลเป็น:
(cmd1 < cmd2) > cmd3
หรือ
cmd1 < (cmd2 > cmd3)
คำตอบ:
ระบุมาตรฐาน POSIXว่าการเปลี่ยนเส้นทางเปลือกจากซ้ายไปขวา; นั่นคือคำสั่งสำคัญ:
การสร้าง
2>&1มักใช้เพื่อเปลี่ยนเส้นทางข้อผิดพลาดมาตรฐานไปยังไฟล์เดียวกับเอาต์พุตมาตรฐาน ตั้งแต่การเปลี่ยนเส้นทางเกิดขึ้นตั้งแต่ต้นจนจบลำดับของการเปลี่ยนเส้นทางมีความสำคัญ ตัวอย่างเช่น:ls > foo 2>&1
fooนำทั้งสองส่งออกมาตรฐานและข้อผิดพลาดมาตรฐานไปยังแฟ้ม อย่างไรก็ตาม:ls 2>&1 > fooเพียงนำออกมาตรฐานไปยังแฟ้มเนื่องจากข้อผิดพลาดมาตรฐานได้รับการคัดลอกเป็นมาตรฐานการส่งออกก่อนที่จะออกมาตรฐานได้รับคำสั่งให้ไฟล์
foofoo
bash ดำเนินการตามส่วนนี้ของมาตรฐาน:
$ ls doesnotexist > foo 2>&1
$ cat foo
ls: cannot access doesnotexist: No such file or directory
$ ls doesnotexist 2>&1 > foo
ls: cannot access doesnotexist: No such file or directory
$ cat foo
$
สำหรับท่อ:
เนื่องจากการกำหนดไปป์ไลน์ของอินพุตมาตรฐานหรือเอาต์พุตมาตรฐานหรือทั้งสองเกิดขึ้นก่อนการเปลี่ยนเส้นทางจึงสามารถแก้ไขได้โดยการเปลี่ยนเส้นทาง ตัวอย่างเช่น:
$ command1 2>&1 | command2ส่งทั้งส่งออกมาตรฐานและข้อผิดพลาดมาตรฐานของการเข้ามาตรฐานของ
command1command2
ls > foo 2>&1หมายถึงเปลี่ยนเส้นทาง stdout เป็น foo จากนั้นเปลี่ยนเส้นทาง stderr ไปยัง stdout ดังนั้นสิ่งนี้จึงไม่ได้ผล คำสั่งที่สองในทำนองเดียวกันควรทำงาน ฉันหายไปนี่อะไร
bashเป็นไปตาม POSIX โดยทั่วไปยกเว้นในสถานการณ์ที่ระบุไว้ที่นี่ซึ่งbashพฤติกรรมเริ่มต้นแตกต่างกัน เพื่อให้bashสอดคล้องมากขึ้นคุณสามารถใช้--posixตัวเลือก
ls > foo 2>&1ดำเนินการเช่นนี้: ครั้งแรกออกมาตรฐานถูกเปลี่ยนเส้นทางไปแล้วข้อผิดพลาดมาตรฐานถูกเปลี่ยนเส้นทางไปออกมาตรฐานซึ่งขณะนี้ไฟล์foo fooตัวอย่างที่สองls 2>&1 > foo, ดำเนินการดังนี้: ข้อผิดพลาดมาตรฐานถูกเปลี่ยนเส้นทางไปยังเอาต์พุตมาตรฐานก่อนที่จะเปลี่ยนเส้นทางเอาต์พุตfooมาตรฐานดังนั้นข้อผิดพลาดมาตรฐานจะถูกสะท้อนแบบโลคัลแทนที่จะถูกชี้นำไปยังไฟล์
ls 2>&1 >foo บางทีคุณอาจคิดแบบนี้ stderr จาก 'ls' ถูกเปลี่ยนเส้นทางไปยัง stdout สิ่งนี้จะเกิดขึ้น! มันจะไปที่ stdout ที่ได้รับมอบหมายในปัจจุบันไปโดยไม่คำนึงถึงคำสั่งเพิ่มเติมใด ๆ ที่เกี่ยวข้องกับ stdout .. (เพราะนี่เป็นคำสั่งนายก / แรก ) .. จากนั้นก็มาอีกคำสั่งที่บอกว่า stdout จะไป "foo", และมันจะ ... จำไว้ว่า: stderr ไม่ได้แปลงไปสู่การเป็น stdout จริง ๆ .. มันแค่ไปที่ที่ stdout ได้รับมอบหมายในเวลาที่มีคำสั่ง (เช่นอาคารผู้โดยสาร)
ฉันเดาไม่ เครื่องหมายวงเล็บคู่หมายถึง sub-shell แต่ในกรณีนี้จะไม่มีการเริ่มเชลล์ย่อยเนื่องจากการเปลี่ยนเส้นทาง ทุบตีเพียงฟีดcmd2เข้า stdin stdout cmd3และฟีดเข้าไป
ฉันคิดว่าคุณหมายถึงอะไรเช่นcmd1 | cmd2 | cmd3? เพราะไฟล์ของคุณcmd2และcmd3ปกติแล้วจะเป็น "cmds" แทน