คำสั่ง ls ทำงานแตกต่างกันไปขึ้นอยู่กับผู้รับ


12

คำสั่งเหมือนlsรู้ว่า stdout มันคืออะไร?

ดูเหมือนว่าlsจะทำงานแตกต่างกันไปขึ้นอยู่กับว่า stdout เป้าหมายคืออะไร เช่นถ้าฉัน:

ls /home/matt/tmp 

ผลลัพธ์คือ:

a.txt b.txt c.txt

อย่างไรก็ตามถ้าฉันทำ

ls /home/matt/tmp | cat

ผลลัพธ์คือ (เช่นบรรทัดใหม่ต่อผลลัพธ์):

a.txt
b.txt
c.txt

กระบวนการผ่านไฟล์ descriptor 1 สำหรับ stdout ใช่ไหม? มันกำหนดวิธีการจัดรูปแบบผลลัพธ์ได้อย่างไร ตัวอธิบายไฟล์เปิดเผยข้อมูลหรือไม่


unix.stackexchange.com/q/157285/4671ที่เกี่ยวข้อง, unix.stackexchange.com/q/63108/4671และที่เกี่ยวข้อง ดูเหมือนว่าจะเป็นหัวข้อยอดนิยม นี่อาจเป็นล่อแหลมของหนึ่งในเหล่านี้
Faheem Mitha

คำตอบ:


22

lsใช้โปรแกรมisatty()ที่จะทราบว่า FD 1 เป็น TTY หรือสิ่งอื่น (ท่อไฟล์ ฯลฯ ... ) จากman 3 isatty:

int isatty(int fd);

รายละเอียดการทดสอบฟังก์ชั่นไม่ว่าจะเป็นที่บ่งแฟ้มเปิดหมายถึงขั้ว
isatty()fd


อัปเดต:บรรทัดที่ 1538 ls.cมาจาก coreutils (แก้ไข git 43a987e1):

  if (isatty (STDOUT_FILENO))
    {
      format = many_per_line;
      /* See description of qmark_funny_chars, above.  */
      qmark_funny_chars = true;
    }

( many_per_lineควรอธิบายด้วยตนเอง)


8

ไม่ใช่คำตอบที่แน่นอน แต่เป็นแบบอย่าง ใน Bash script คุณสามารถใช้เอฟเฟ็กต์แบบเดียวกันกับtest/ [['s -t:

-t FD True if FD is opened on a terminal.

ใช้แบบนี้:

bash-4.2$ where() { [[ -t 1 ]] && echo 'my output goes to TTY' || echo 'my output is redirected'; }

bash-4.2$ where
my output goes to TTY

bash-4.2$ where | cat
my output is redirected

bash-4.2$ where > test.file
bash-4.2$ cat test.file
my output is redirected

6

จากls(1) คู่มือ OpenBSD :

โดยค่าเริ่มต้น ls แสดงหนึ่งรายการต่อบรรทัดไปยังเอาต์พุตมาตรฐาน ข้อยกเว้นสำหรับเทอร์มินัลหรือเมื่อระบุอ็อพชัน -C, -m หรือ -x

จากนั้นต่อมา

-1 (ตัวเลขที่เป็นตัวเลข `` one '') บังคับให้เอาต์พุตเป็นหนึ่งรายการต่อบรรทัด นี่คือค่าเริ่มต้นเมื่อเอาต์พุตไม่ได้ไปที่เทอร์มินัล

[ ... ]

-C แรงหลายคอลัมน์เอาท์พุท; นี่เป็นค่าเริ่มต้นเมื่อเอาต์พุตคือเทอร์มินัล


1

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

สำหรับต้นแบบisatty()กลไกชี้ออกไปแล้วจากStéphaneดอนดูls.c

ls -G /
ls -G / | cat
script -q /dev/null ls -G / | sed $'s/\r$//g' | cat

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