คุณได้รับคำตอบที่ดีมากแล้ว ฉันขอเน้นว่ามีสองแนวคิดที่แตกต่างกันที่นี่ความเข้าใจซึ่งช่วยอย่างมาก:
พื้นหลัง: ตัวอธิบายไฟล์เทียบกับตารางไฟล์
ไฟล์ descriptor ของคุณเป็นเพียงตัวเลข 0 ... n ซึ่งเป็นดัชนีในตาราง descriptor ไฟล์ในกระบวนการของคุณ ตามแบบแผน STDIN = 0, STDOUT = 1, STDERR = 2 (โปรดทราบว่าคำศัพท์STDINอื่น ๆ ที่นี่เป็นเพียงสัญลักษณ์ / มาโครที่ใช้โดยการประชุมในภาษาการเขียนโปรแกรมและหน้าคนไม่มีวัตถุ "จริง" เรียกว่า STDIN สำหรับ จุดประสงค์ของการสนทนานี้ STDIN คือ 0 เป็นต้น)
ตารางตัวอธิบายไฟล์นั้นในตัวมันเองไม่มีข้อมูลใด ๆ เกี่ยวกับไฟล์จริง แต่จะมีตัวชี้ไปยังตารางไฟล์อื่น หลังมีข้อมูลเกี่ยวกับไฟล์จริง (หรืออุปกรณ์บล็อกหรือไปป์หรืออะไรก็ตามที่ Linux สามารถจัดการผ่านกลไกไฟล์) และข้อมูลเพิ่มเติม (เช่นไม่ว่าจะเป็นการอ่านหรือเขียน)
ดังนั้นเมื่อคุณใช้>หรือ<ในเชลล์คุณเพียงแค่เปลี่ยนพอยน์เตอร์ของไฟล์ descriptor ตามลำดับเพื่อชี้ไปยังสิ่งอื่น ไวยากรณ์2>&1เพียงแค่บ่งชี้ 2 ไปที่ใดก็ได้ 1 คะแนน > file.txtเพียงแค่เปิดfile.txtสำหรับการเขียนและให้ STDOUT (ไฟล์ decsriptor 1) ชี้ไปที่
มีสารพัดอื่น ๆ เช่น2>(xxx)  (เช่น: สร้างกระบวนการใหม่ทำงานxxxสร้างไพพ์เชื่อมต่อไฟล์ descriptor 0 ของกระบวนการใหม่ไปยังจุดสิ้นสุดการอ่านของไพพ์และเชื่อมต่อไฟล์ descriptor 2 ของกระบวนการดั้งเดิมไปยังจุดสิ้นสุดการเขียนของ ท่อ).
นี่เป็นพื้นฐานสำหรับ "file handle magic" ในซอฟต์แวร์อื่นที่ไม่ใช่เชลล์ของคุณ ตัวอย่างเช่นในสคริปต์ Perl ของคุณให้dupไลเซนส์ตัวอธิบายไฟล์ STDOUT เป็นอีกตัวหนึ่ง (ชั่วคราว) จากนั้นเปิด STDOUT อีกครั้งเป็นไฟล์ชั่วคราวที่สร้างขึ้นใหม่ จากจุดนี้เป็นต้นไปเอาต์พุต STDOUT ทั้งหมดจากสคริปต์ Perl ของคุณเองและการsystem()เรียกใช้สคริปต์ทั้งหมดจะสิ้นสุดในไฟล์ชั่วคราวนั้น เมื่อเสร็จแล้วคุณสามารถdupSTDOUT ของคุณไปที่ descriptor ชั่วคราวที่คุณบันทึกไว้และ presto ทั้งหมดนี้เป็นเหมือนเดิม คุณสามารถเขียนไปที่ descriptor ชั่วคราวนั้นได้ในขณะที่เอาท์พุท STDOUT ที่แท้จริงของคุณไปที่ไฟล์ชั่วคราวคุณยังสามารถเอาท์พุทของจริง ๆ ไปยังSTDOUT ตัวจริง
ตอบ
หากต้องการใช้ข้อมูลพื้นหลังที่ให้ไว้กับคำถามของคุณ:
  เชลล์สั่งรันคำสั่งและเปลี่ยนเส้นทางสตรีมในลำดับใด
จากซ้ายไปขวา 
  <command> > file.txt 2>&1
- forkออกกระบวนการใหม่
- เปิดfile.txtและเก็บตัวชี้ไว้ในตัวอธิบายไฟล์ 1 (STDOUT)
- ชี้ STDERR (ตัวอธิบายไฟล์ 2) ไปยังสิ่งที่ fd 1 ชี้ไปในขณะนี้ (ซึ่งเป็นfile.txtหลักสูตรที่เปิดอยู่แล้ว)
- exec- <command>
  เห็นได้ชัดว่านี่เปลี่ยนเส้นทาง stderr ไปยัง stdout ก่อนจากนั้น stdout ที่ได้จะถูกเปลี่ยนเส้นทางไปยัง file.txt
นี่จะสมเหตุสมผลถ้ามีเพียงหนึ่งตาราง แต่ตามที่อธิบายข้างต้นมีสอง ตัวให้คำอธิบายไฟล์ไม่ได้ชี้ไปซ้ำ ๆ กันมันไม่มีเหตุผลที่จะคิดว่า "เปลี่ยนเส้นทาง STDERR ไปยัง STDOUT" ความคิดที่ถูกต้องคือ "ชี้ STDERR ไปยังทุกจุดของ STDOUT" หากคุณเปลี่ยน STDOUT ในภายหลัง STDERR จะคงอยู่ในที่เดิมมันจะไม่ไปพร้อมกับการเปลี่ยนแปลงเพิ่มเติมใน STDOUT อย่างน่าอัศจรรย์