`cat <> file` ทำงานอย่างไร


42

cat < fileพิมพ์เนื้อหาของไฟล์ไปยัง stdout

cat > fileอ่าน stdin จนกว่าCtrl+ Dมีการตรวจพบและป้อนข้อความถูกเขียนไปยังแฟ้ม

cat <> fileอย่างน้อยในเวอร์ชัน Bash ของฉันพิมพ์เนื้อหาของไฟล์อย่างมีความสุข (โดยไม่มีข้อผิดพลาด) แต่ไม่ได้แก้ไขไฟล์หรืออัปเดตการประทับเวลาการแก้ไข

มาตรฐาน Bash แสดงให้เห็นถึงการเพิกเฉยที่ปรากฏ>ในข้อความที่สามได้อย่างไรและที่สำคัญกว่านั้นคือการทำอะไร

คำตอบ:


47

Bash ใช้<>เพื่อสร้างdescriptor ไฟล์อ่าน - เขียน :

ผู้ประกอบการเปลี่ยนเส้นทาง

[n]<>word

ทำให้ไฟล์ที่มีชื่อคือส่วนขยายของคำที่จะเปิดสำหรับทั้งการอ่านและการเขียนบน file descriptor n หรือบน file descriptor 0 หากไม่ได้ระบุ n หากไฟล์ไม่มีอยู่ไฟล์จะถูกสร้างขึ้น

cat <> fileเปิดfileอ่าน - เขียนและผูกเข้ากับ descriptor 0 (อินพุตมาตรฐาน) มันเทียบเท่ากับ< fileโปรแกรมที่เขียนขึ้นอย่างสมเหตุสมผลเพราะไม่มีใครมีแนวโน้มที่จะลองเขียนไปยังอินพุตมาตรฐานตามปกติ แต่ถ้ามีใครทำได้ก็สามารถทำได้

คุณสามารถเขียนโปรแกรม C ง่ายในการทดสอบที่ออกมาโดยตรง - write(0, "hello", 6)จะเขียนhelloลงไปในfileทางเข้ามาตรฐาน

<>ควรทำงานในเชลล์ที่สอดคล้องกับPOSIX อื่นใดที่มีเอฟเฟกต์เดียวกัน


1
กำลังเขียน ... ไปยัง stdin หรือไม่ ... มีกรณีการใช้งานที่ถูกต้องสำหรับสิ่งนี้หรือไม่?
Qix

3
ฉันไม่สามารถนึกถึงสิ่งที่ดีได้เลย การให้ descriptor อย่างชัดเจน ( 4<>file) นั้นมีประโยชน์และฉันคิดว่า 0 จะเป็นค่าเริ่มต้นที่ดีเมื่อคุณละทิ้ง การอ่านจาก stdout ไม่ได้ดีไปกว่านี้แล้ว
Michael Homer

5
<>ยังมีประโยชน์ในบางระบบ (เช่น Linux) เพื่อเปิดไปป์ที่มีชื่อโดยไม่ปิดกั้นจนกว่ากระบวนการอื่นจะเปิดขึ้นเพื่อการเขียน
Stéphane Chazelas

1
@Qix: เขียนดี (0, "รหัสผ่าน:", 10) เป็นวิธีที่ดีในการขอรหัสผ่านถ้าคุณตั้งใจจะถามเกี่ยวกับสิ่งที่ชอบ tty ฉันเคยเห็นมันใน stderr แต่ไม่มีเหตุผลโดยเฉพาะอย่างยิ่งเทคนิคเดียวกันไม่สามารถใช้งานได้ใน stdin
โจชัว

3
@Qix - จากPOSIX Rationale - <>โอเปอเรเตอร์อาจมีประโยชน์ในการเขียนแอปพลิเคชันที่ทำงานกับเทอร์มินัลหลายเครื่องและบางครั้งต้องการเริ่มเชลล์ เชลล์นั้นจะไม่สามารถเรียกใช้แอปพลิเคชันที่ทำงานจากเทอร์มินัลการควบคุมทั่วไปยกเว้นว่าจะสามารถใช้<>... เช่น ... เพจเจอร์moreซึ่งอ่านจากข้อผิดพลาดมาตรฐานเพื่อรับคำสั่งของมันดังนั้นอินพุตมาตรฐานและเอาต์พุตมาตรฐาน มีทั้งสำหรับการใช้งานตามปกติ cat food | more - >/dev/tty03 2<>/dev/tty03
mikeserv

38

<> fileเปิดแฟ้ม (บนไฟล์อธิบาย 0 (stdin) โดยค่าเริ่มต้นเช่น<) ใน+ เขียนอ่านโหมดโดยไม่ต้องตัดและการสร้างไฟล์ถ้ามันไม่ได้มีอยู่ก่อน

ที่สอดคล้องกับO_RDWR|O_CREATค่าสถานะที่ส่งผ่านไปยังการopen()เรียกระบบ โดยคมชัด<เป็นO_RDONLYและ>เป็นและO_WRONLY|O_CREAT|O_TRUNC>> O_WRONLY|O_CREAT|O_APPEND

การเขียน stdin นั้นไม่ค่อยมีประโยชน์เนื่องจากแอปพลิเคชันมักจะไม่เขียนลง stdin แอปพลิเคชันมักไม่คาดว่าจะอ่านและเขียนไฟล์ descriptor ที่พวกเขาได้รับเมื่อเริ่มต้น; พวกเขามักจะอ่านจาก stdin (หรืออธิบายไฟล์ที่พวกเขาเปิดตัวเอง) และเขียนไปยัง stdout หรือ stderr (หรืออธิบายไฟล์ที่พวกเขาเปิดตัวเอง)

<> สามารถใช้มันได้:

  • คุณอาจต้องการcat <> fileมากกว่าcat < fileถ้าคุณไม่ต้องการให้คำสั่งล้มเหลวหากfileไม่มีอยู่ แต่fileสร้างว่างเปล่าแทน
  • ลักษณะที่ไม่ถูกตัดทอน<>ทำให้มีประโยชน์ในการเขียนทับไฟล์ ในกรณีดังกล่าวอย่างไรก็ตามโดยทั่วไปคุณจะไม่ใช้มันใน file descriptor 0:

    printf xxx 1<> file

    แทนที่ครั้งแรก 3 ไบต์ด้วยfilexxx

  • ในบางระบบเช่น Linux <>บนไปป์ที่มีชื่อ (FIFO) เปิดไปป์ที่มีชื่อโดยไม่มีการปิดกั้น (โดยไม่รอให้กระบวนการอื่นเปิดปลายอีกด้าน) และทำให้มั่นใจว่าโครงสร้างของท่อนั้นยังมีชีวิตอยู่ ตัวอย่างเช่นใน:

    mkfifo pipe; sed 's/foo/bar/g' <> pipe

    sedจัดการข้อมูลที่เข้ามาจากจำนวนของกระบวนการอื่น ๆ ที่เขียนถึงมันใด ๆ eofและไม่เคยเห็น


1
โปรดทราบว่าใน AT&T ksh93 ให้ใช้<>ค่าเริ่มต้นเป็น1<>(stdout) แทน0<>(stdin) นี่เป็นข้อผิดพลาดในการปฏิบัติตาม POSIX ที่ฉันรายงานและจะได้รับการแก้ไขในรุ่นถัดไป github.com/att/ast/issues/75แต่จนกว่ารุ่น ksh93 ปัจจุบันจะไม่ใช้งานคุณจะต้องรวมหมายเลขตัวอธิบายไฟล์เพื่อใช้งานแบบ<>พกพา
Martijn Dekker

@ MartijnDekker ฉันรู้ว่าฉันเป็นคนหนึ่งที่บอกคุณเกี่ยวกับมันในตอนแรก ;-) โปรดทราบว่าเป็นเพียงสำหรับ ksh93t + (ซึ่งพฤติกรรมเปลี่ยนไป) และเหนือ
Stéphane Chazelas

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