คำสั่งนี้ถูกกฎหมายอย่างไร “> file1 <file2 cat”


61

สมมติว่าfile2มีอยู่แล้วคำสั่ง

> file1 < file2 cat

ดูเหมือนจะคัดลอกเนื้อหาของการfile2file1

แต่ฉันไม่เข้าใจโครงสร้างนี้

ฉันเข้าใจว่า "ไม่มีสิ่งใด" กำลังถูกนำไปสู่file1(สร้างหรือลบเนื้อหา) แล้วเนื้อหาของจะถูกนำไปยังfile2file1

เป็นเพราะเหตุใดcatหลังจากที่file2? จะทราบได้อย่างไรcat file2ว่าตัวถูกดำเนินการไม่ได้อยู่ในลำดับที่ถูกต้อง?


11
"ลำดับที่ถูกต้อง" คืออะไร คุณสามารถให้ลิงค์ไปยังแหล่งข้อมูล / สื่อการเรียนรู้ที่อธิบาย "ลำดับที่ถูกต้อง" ได้หรือไม่?
การแข่งขัน Lightness กับโมนิก้า

7
เมื่อถามคำถามเช่นนี้คุณควรระบุเชลล์ กรณีที่แตกต่างกันมีกรณีขอบที่แตกต่างกันโดยเฉพาะการเปลี่ยนเส้นทาง
chrylis -on strike-

คำตอบ:


117

ก่อนที่เชลล์จะประมวลผลcatคำสั่งบนบรรทัดคำสั่งมันจะค้นหาการเปลี่ยนเส้นทาง

มีการเปลี่ยนเส้นทางสองแบบ:

  1. >file1file1ซึ่งจะทำให้การส่งออกมาตรฐานของคำสั่งไป
  2. <file2file2ซึ่งจะทำให้เข้ามาตรฐานของคำสั่งมาจาก

ความจริงที่ว่าการเปลี่ยนเส้นทางเหล่านี้อยู่ในตำแหน่งที่ไม่ได้ผลบนบรรทัดคำสั่งไม่สำคัญ

$ cat <file2 >file1

เป็นเช่นเดียวกับ

$ <file2 cat >file1

ซึ่งเหมือนกับ

$ <file2 >file1 cat

etc.¹

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

ความแตกต่างระหว่างcat fileและcat <file(หรือถ้าคุณต้องการ<file cat) ก็คือในกรณีแรกcatยูทิลิตี้เองกำลังเปิดไฟล์ซึ่งได้รับเป็นตัวถูกดำเนินการในบรรทัดคำสั่งสำหรับการอ่านในขณะที่ในกรณีที่สองเปลือกจะ เปิดไฟล์และเชื่อมต่อcatสตรีมอินพุตกับit² ในกรณีที่สองcatจะสังเกตเห็นว่ามันไม่ได้รับตัวถูกดำเนินการไฟล์และจะเปลี่ยนเป็นการอ่านจากอินพุตมาตรฐานโดยอัตโนมัติ นี่คือคุณสมบัติของcatและยูทิลิตี้อื่น ๆ ไม่ใช่สิ่งที่ยูทิลิตี้ทั้งหมดทำ

cat-นอกจากนี้ยังจะอ่านจากอินพุตมาตรฐานของมันถ้ามันให้ถูกดำเนินการ นี่เป็นพิเศษสำหรับcatยูทิลิตี้อื่น ๆ เท่านั้น (นั่นคือไม่มีสิ่งใดที่เชลล์ทำ) ที่จะใช้catในไฟล์ในไดเรกทอรีปัจจุบันที่มีชื่อเป็น เพิ่มเส้นทางไปยังชื่อไฟล์เช่น-./-

¹ ลำดับของการเปลี่ยนเส้นทางยังคงเป็นสิ่งที่สำคัญภายใต้สถานการณ์บาง; ด้วยcat <file2 >file1ตัวอย่างเช่นfile1จะไม่ถูกตัดทอนถ้าfile2ไม่สามารถเข้าถึงได้ (เปลี่ยนเส้นทางที่มีการแยกวิเคราะห์จากซ้ายไปขวา) อย่างไรก็ตามการวางตำแหน่งสัมพัทธ์ของคำcatยังคงเป็นการสุ่มและจะไม่มีผลกับสิ่งนี้

² ดูเพิ่มเติมที่คำถาม " cat มอบข้อผิดพลาดต่าง ๆ เมื่อเปิดไฟล์ที่ไม่มีอยู่ "


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

$ sort file >file

ที่นี่เชลล์จะตัดทอน (ว่าง) ไฟล์fileก่อนที่จะดำเนินการsort fileและเชื่อมต่อsortเอาต์พุตมาตรฐานของไฟล์ sortยูทิลิตี้จากนั้นจะเปิดfileและจัดเรียงเนื้อหา (ซึ่งเป็นอะไร) ผล (อะไร) fileจะถูกส่งผ่านกระแสออกมาตรฐานการ

การแก้ไขในกรณีนี้โดยเฉพาะ (สำหรับการเรียงลำดับไฟล์ "ในสถานที่") คือ

$ sort -o file file

หรือ

$ sort file >file.sorted && mv file.sorted file

ซึ่งจะมากหรือน้อยsortเมื่อใช้-oไฟล์เพื่อระบุชื่อไฟล์เอาต์พุต


เพียงสำรองคำสั่งที่การเปลี่ยนเส้นทางอาจนำหน้าชื่อจริงของยูทิลิตี้ในบรรทัดคำสั่ง:

"คำสั่งอย่างง่าย" คือลำดับของการกำหนดตัวแปรและการเปลี่ยนเส้นทางที่เป็นทางเลือกในลำดับใดก็ได้ตามด้วยคำและการเปลี่ยนเส้นทางซึ่งสิ้นสุดลงโดยผู้ควบคุม [อ้างอิง: ภาษาคำสั่ง POSIX Shell 2.9.1 คำสั่งง่าย ๆ ]

และยังเกี่ยวกับการเปลี่ยนเส้นทางที่ไม่ได้เป็นส่วนหนึ่งของตัวถูกดำเนินการของยูทิลิตี้:

จำนวนที่เป็นทางเลือกโอเปอเรเตอร์การเปลี่ยนเส้นทางและคำจะไม่ปรากฏในอาร์กิวเมนต์ที่ให้ไว้กับคำสั่งที่จะดำเนินการ (ถ้ามี) [อ้างอิง: การเปลี่ยนเส้นทางภาษาคำสั่ง POSIX Shell 2.7]


14
@Steve อิสระในการย้ายการเปลี่ยนเส้นทางไปรอบ ๆ สามารถใช้เพื่อทำให้คำสั่งบางอย่างชัดเจนยิ่งขึ้นเช่นไปป์ไลน์ที่มีการเปลี่ยนเส้นทางอินพุตที่จุดเริ่มต้น<in foo | bar >outทำให้ทุกอย่างอยู่ในลำดับที่เป็นตรรกะ ฉันยังชอบถ้าecho >&2 Something bad happenedข้อผิดพลาดออกจากเปลือกสคริปต์ แต่>out <in catเป็นเพียงความงงงัน

2
อาจsort file >fileสำเร็จได้อย่างถูกต้องอย่างไร?
seth10

11
@setht sort -o file fileด้วย
Kusalananda

6
คำตอบที่ดี โปรดทราบว่าคำสั่งซื้อมีความสำคัญ < file1 > file2 catจะดีกว่า> file2 < file1 catที่จะหลีกเลี่ยงfile2การถูกตัดทอนถ้าfile1ไม่สามารถเปิดได้
Stéphane Chazelas

3
สิ่งที่ควรระวัง: เมื่อเชื่อมโยงไปยัง POSIX ที่มีแฟรกเมนต์ HTML จะเป็นการดีกว่าที่จะระบุรุ่นที่แน่นอน (เช่นpubs.opengroup.org/onlinepubs/9699919799.2016edition ) เนื่องจากชิ้นส่วนนั้นมีการเปลี่ยนแปลงระหว่างรุ่นของสเปครุ่นเดียวกัน (ลิงก์จำนวนมากในคำตอบในเว็บไซต์นี้รวมถึงของฉันตอนนี้ผิดเนื่องจากชิ้นส่วนชี้ไปในตำแหน่งที่ไม่ถูกต้องหลังจากรุ่น 2016 ได้รับการเผยแพร่)
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.