น้อยกว่า file1 file2 | แมว - ทำไมจึงใช้งานได้


21

เมื่อฉันใช้less file1 file2ฉันจะได้รับทั้งไฟล์ที่แสดงใน "less buffer viewer" แต่less file1 file2 | catพิมพ์เนื้อหาของไฟล์ทั้งสองต่อท้าย stdout จะทราบได้อย่างไรว่าควรแสดง "โปรแกรมดูบัฟเฟอร์น้อย" หรือสร้างเอาต์พุตไปยัง stdout สำหรับคำสั่งถัดไป มีกลไกอะไรที่ใช้ในการทำสิ่งนี้?

คำตอบ:


30

lessพิมพ์ข้อความไปยัง stdout stdout ไป

  • ไปยังเทอร์มินัล (/ dev / tty?) และเปิดตัวแสดงบัฟเฟอร์เริ่มต้น
  • ผ่านท่อเมื่อท่อมัน programm อื่นโดยใช้ | ( less text | cut -d: -f1)
  • ไปยังไฟล์เมื่อเปลี่ยนเส้นทางด้วย> ( less text > tmp)

มีฟังก์ชั่น C ที่เรียกว่า "isa tty " ซึ่งตรวจสอบว่าเอาต์พุตจะเป็น tty (น้อยกว่า 4.81, main.c, บรรทัด 112) catถ้าเป็นเช่นนั้นจะใช้มุมมองบัฟเฟอร์มิฉะนั้นก็จะทำงานเช่น

ในทุบตีคุณสามารถใช้การทดสอบ (ดูman test)

  • -t FD file descriptor FD ถูกเปิดบนเทอร์มินัล
  • -p ไฟล์อยู่และเป็นไปป์ที่มีชื่อ

ตัวอย่าง:

[[ -t 1 ]] && \
    echo 'STDOUT is attached to TTY'

[[ -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a pipe'

[[ ! -t 1 && ! -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a redirection'

1
@tfh หาก STDOUT ไม่ได้เชื่อมต่อกับไพพ์หรือการเปลี่ยนเส้นทางมันถูกต้องที่พวกเขาจะไม่พิมพ์ STDOUT ที่แนบมากับไพพ์หรือการเปลี่ยนเส้นทาง ใส่ทั้งสามไว้ในสคริปต์ โทรbash script.sh, bash script.sh | cat, bash script.sh > fileและดูสิ่งที่คุณจะได้รับการส่งออก
hvd

1
stdoutไม่ใช่สิ่งที่สามารถ "เขียนไปยังไฟล์" มันเป็นสิ่งที่คุณจะ write() lessไม่ต้องทำอะไรที่แตกต่างกันขึ้นอยู่กับว่าเอาต์พุตเป็นไฟล์, ไพพ์, ซ็อกเก็ตหรืออุปกรณ์บล็อคหรืออะไรก็ตาม มันสำคัญแค่ว่ามันไม่ใช่ tty ดังนั้นมันจึงมีพฤติกรรมเช่นcatนั้น (ฉันถือว่าคุณรู้เรื่องนี้และเลือกคำที่ผิดเพื่ออธิบาย แต่ฉันคิดว่าฉันจะชี้ประเด็นนี้ให้ผู้อ่านคนอื่น ๆ )
Peter Cordes

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

@tfh: lessไม่ไม่ "คิดออก" ที่catอยู่ถัดไป มันแค่ทำตัวเหมือนcatไม่ว่าอะไรจะเกิดขึ้นต่อไปถ้า stdout ไม่ใช่ tty
Peter Cordes

@MichaelD: ขอบคุณแก้ไขคำตอบของฉัน ฉันแค่เดาว่าlessจะไปข้างหน้าและใช้หนึ่ง TCGETS เพื่อให้ได้ขนาดเทอร์มินัลหรือค้นพบว่ามันไม่ใช่ tty แต่เห็นได้ชัดว่าฉันเดาผิด
Peter Cordes

6

lessตรวจสอบว่ามันstdoutเป็นขั้วและทำงานเหมือนcatเมื่อมันไม่ได้ (คัดลอก stdin เพื่อ stdout จนกระทั่ง EOF)

คุณลักษณะนี้ช่วยให้คุณสามารถเขียนสคริปต์หรือโปรแกรมที่ส่งเอาต์พุต (เช่น--helpเอาต์พุต) ตลอดเวลาlessขณะที่ยังยอมให้เปลี่ยนเส้นทางไปยังไฟล์ได้ง่าย มันจะดูดถ้าsome_command --fullhelp > help.txtยังคงรอสเปซบาร์บน stdin เพื่อเลื่อนดูข้อความหรืออะไรซักอย่าง บางคำสั่ง (เช่นman) ตรวจสอบว่าเอาต์พุตของตนเองเพื่อตัดสินใจว่าจะส่งเอาต์พุตผ่านเพจเจอร์หรือไม่ ถ้าคุณใช้มันไม่เคยเรียกคุณman ls > ls.txt$PAGER

lessพฤติกรรมคล้ายแมวนั้นมีประโยชน์ถ้าคุณลืมที่จะแก้ไขมันออกมาจากสายการบินเดียวเมื่อเพิ่มขั้นตอนเพิ่มเติมลงในไปป์ไลน์ด้วย


lessจำเป็นต้องทราบขนาดเทอร์มินัล (ขนาดหน้าจอเพื่อทราบจำนวนบรรทัดที่จะแสดงพร้อมกัน) ioctl(2)จะใช้ในการstdoutจะกลับมา ENOTTY บนไม่ใช่ขั้วดังนั้นจึงไม่สามารถหลีกเลี่ยงการจัดการกรณีที่ไม่ใช่ขั้วอยู่แล้ว lessใช้งานจริงisatty(3)ก่อนตรวจสอบขนาดเทอร์มินัล แต่isattyทำงานได้โดยลองใช้ ioctl แบบ tty-only และตรวจสอบหาข้อผิดพลาด

แม้แต่เพจเจอร์ธรรมดา ๆ อย่างmore(1)(อย่างน้อยรุ่น util-linux) ก็มีฟีเจอร์นี้เพราะมันอาจเป็นพฤติกรรมที่มีสติที่ง่ายที่สุดในการนำไปใช้ในกรณีนั้น


โปรดทราบว่าเมื่อคุณไพพ์บางอย่างลงใน less (เช่นgrep foo bar.txt | less) มันจะต้องเปิดขึ้น/dev/ttyเพื่อป้อนคีย์บอร์ด (คุณสามารถดูได้ด้วยecho foo | strace less)

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