สัญลักษณ์ท่อ linux“ |” ทำหน้าที่อะไร? [ซ้ำ]


23

นี่คือคำสั่งที่เรียงลำดับไฟล์ในโฟลเดอร์ตามลำดับย้อนกลับ

ls | sort -r

อะไร|สัญลักษณ์ในคำสั่งที่ทำอย่างไร

สิ่งที่ฉันกำลังมองหาจริงๆที่นี่คือคำอธิบายระดับสูง (เข้าใจง่าย) ของไพพ์สำหรับผู้เริ่มต้นใช้งาน Linux ฉันเห็นคำถามอื่นเกี่ยวกับท่อที่นี่ใน Superuser แต่ไม่มีสิ่งใดที่ทำให้เกิดคำตอบที่อธิบายในแง่ง่าย ๆ ว่าพวกเขาทำอะไรและแตกต่างจากการเปลี่ยนเส้นทางอย่างไร ( >หรือ<สัญลักษณ์)


7
สิ่งนี้ไม่เกี่ยวข้องกับ Linux (ซึ่งเป็นเคอร์เนล) ท่อโดยทั่วไปเป็นวิธีการป้อนข้อมูลเข้า / ส่งออกอีกครั้งในเชลล์เช่นทุบตีมันไม่แตกต่างกัน สิ่งเดียวที่พิเศษเกี่ยวกับ a |คือมันไม่ได้ใช้ชื่อเอาต์พุตจากคำสั่ง l-hand จะถูกส่งโดยตรงไปยังอินพุตสำหรับคำสั่งที่ด้านซ้ายมือของไพพ์
Andon M. Coleman

สำหรับบทเรียนประวัติศาสตร์เกี่ยวกับเรื่องนี้อ่านlinfo.org/pipe.html
Fredrik Pihl

ls -1r(หมายเหตุหนึ่งอาร์กิวเมนต์จำนวน) ls | sort -rควรผลิตผลคล้ายกับ
Ivan Chau

ฉันชอบที่จะอธิบายอย่างนั้น: ไปป์ใช้เอาท์พุทของคำสั่งเดียวและทำให้มันใช้งานได้สำหรับคำสั่งต่อไปนี้ cat /somefile | grep coolตัวอย่างเช่นคุณสามารถทำได้ สิ่งนี้จะนำเอาท์พุทของ somefile และทำให้พร้อมใช้งานสำหรับ grep แล้ว grep จะพิมพ์ทุกบรรทัดด้วยคำว่า cool
JohnDoea

คำตอบ:


26

ต่อไปนี้เป็นบิตที่จะช่วยผู้ใช้ใหม่

ก่อนอื่นจำเป็นต้องเข้าใจแนวคิดของอินพุตมาตรฐานและเอาต์พุตมาตรฐาน

ใน Linux และระบบปฏิบัติการคล้าย UNIX อื่น ๆ แต่ละกระบวนการมีอินพุตมาตรฐาน ( stdin) และเอาต์พุตมาตรฐาน ( stdout) สถานการณ์ปกติคือstdinแป้นพิมพ์ของคุณและstdoutเป็นหน้าจอหรือหน้าต่างเทอร์มินัลของคุณ

ดังนั้นเมื่อคุณเรียกใช้ก็จะโยนมันออกไปls stdoutหากคุณไม่ทำอะไรเลยมันจะไปที่หน้าจอหรือหน้าต่างเทอร์มินัลและคุณจะดู

ตอนนี้คำสั่ง Linux บางคำสั่งจะโต้ตอบกับผู้ใช้และใช้stdinในการทำเช่นนั้นตัวแก้ไขข้อความของคุณจะเป็นหนึ่งในนั้น มันอ่านจากที่จะยอมรับการกดแป้นพิมพ์ของคุณทำสิ่งแล้วสิ่งที่จะเขียนstdinstdout

อย่างไรก็ตามยังมีคำสั่งที่ไม่ใช่แบบโต้ตอบหรือ "ตัวกรอง" ที่ไม่ทำงานแบบโต้ตอบ แต่ต้องการข้อมูลจำนวนมาก คำสั่งเหล่านี้จะนำทุกอย่างstdinไปทำสิ่งนั้นแล้วโยนมันไปstdout

ลองดูคำสั่งอื่นที่เรียกว่าdu- ย่อมาจากการใช้งานดิสก์ du /usrตัวอย่างเช่นจะพิมพ์ออกมา ( stdoutเช่นเดียวกับคำสั่ง Linux อื่น ๆ ) รายการของทุกไฟล์ในไดเรกทอรีนั้นและมีขนาด:

# du /usr
2312    /usr/games
124     /usr/lib/tc
692     /usr/lib/rygel-1.0
400     /usr/lib/apt/methods
40      /usr/lib/apt/solvers
444     /usr/lib/apt
6772    /usr/lib/gnash

ในขณะที่คุณสามารถบอกได้ทันทีจากค้างคาวมันไม่ได้ถูกจัดเรียงและคุณอาจต้องการให้มันเรียงตามขนาด

sortเป็นหนึ่งในคำสั่ง "ตัวกรอง" ที่จะstdinคัดแยกสิ่งต่าง ๆ ออกมาและเรียงลำดับ

ดังนั้นถ้าเราทำสิ่งนี้:

# du /usr | sort -nr

เราได้สิ่งนี้ซึ่งดีกว่า:

4213348 /usr
2070308 /usr/lib
1747764 /usr/share
583668  /usr/lib/vmware
501700  /usr/share/locale
366476  /usr/lib/x86_64-linux-gnu
318660  /usr/lib/libreoffice
295388  /usr/lib/vmware/modules
290376  /usr/lib/vmware/modules/binary
279056  /usr/lib/libreoffice/program
216980  /usr/share/icons

และตอนนี้คุณจะเห็นว่า "ท่อ" เชื่อมต่อกับstdoutคำสั่งหนึ่งไปยังstdinอีก โดยทั่วไปแล้วคุณจะใช้ในสถานการณ์เช่นนี้ซึ่งคุณต้องการกรองเรียงลำดับหรือจัดการกับเอาต์พุตของคำสั่ง สามารถเรียงซ้อนหากคุณต้องการประมวลผลเอาต์พุตผ่านคำสั่งตัวกรองหลายคำสั่ง

ถ้าคุณพิมพ์ด้วยตัวเองก็จะยังคงพยายามที่จะอ่านจากsort stdinเนื่องจากstdinเชื่อมต่อกับแป้นพิมพ์ของคุณแล้วจะรอให้คุณพิมพ์และประมวลผลสิ่งต่าง ๆ จนกว่าคุณจะกด Control-D มันจะไม่แจ้งให้คุณทราบเนื่องจากไม่ได้มีไว้สำหรับใช้โต้ตอบ

เป็นไปได้สำหรับโปรแกรมที่จะบอกว่าstdinเป็นแบบโต้ตอบหรือไม่ดังนั้นบางโปรแกรมอาจทำงานแตกต่างกันถ้าคุณออกมันด้วยตัวเองหรือในตอนท้ายของไพพ์

นอกจากนี้การวางโปรแกรมที่ใช้งานได้แบบโต้ตอบviเท่านั้นจะส่งผลให้คุณมีเวลาที่ไม่ดี

ท่อแตกต่างจากการเปลี่ยนเส้นทางซึ่งข้อมูลถูกสับจากคำสั่งหนึ่งไปยังอีกคำสั่งโดยไม่ถูกเก็บไว้ที่ใดก็ได้ ดังนั้นในตัวอย่างข้างต้นduเอาต์พุตของจะไม่ถูกเก็บไว้ที่ใดก็ได้ เวลาส่วนใหญ่คุณไม่ต้องการสิ่งนี้ด้วยไพพ์เพราะเหตุผลที่ใช้ไพพ์คือการประมวลผลเอาต์พุตของคำสั่งในบางวิธี - แต่มีคำสั่งteeที่ให้คุณมีเค้กและกินมันด้วยเช่นกัน คัดลอกสิ่งที่ได้รับจากstdinทั้งสองstdoutและไฟล์ที่คุณเลือก คุณอาจจะทำสิ่งนี้bashด้วยไวยากรณ์อาร์เคนบางอันที่เกี่ยวข้องกับเครื่องหมายและวงเล็บที่ฉันไม่รู้


โปรดทราบว่านี่ไม่ใช่เอกสิทธิ์ของ Linux หรือแม้แต่ POSIX เชลล์ส่วนใหญ่ (ทั้งหมด?) บน Windows ก็ทำเช่นนี้เช่นกัน และอาจเป็น OS อื่น ๆ
บ๊อบ

ฉันรู้ว่าแนวคิดของstdinและstdoutแตกต่างภายใต้ Windows มากกว่าที่อยู่ภายใต้ Linux แต่อาจไม่มากนักจากมุมมองของ Windows cmd.exeหรือ Powershell
LawrenceC

ฉันอยากรู้อยากเห็นเกี่ยวกับความแตกต่าง - คุณจะอธิบายให้ฟังได้ไหม บางทีในการแชทหากความเห็นไม่ใช่สถานที่ที่ดีสำหรับมัน
บ๊อบ

1
โปรแกรม Win32 ส่วนใหญ่มีอินพุตและเอาต์พุตมาตรฐานแน่นอน GetStdHandle()ตัวอย่างเช่นคุณสามารถเรียกกระบวนการของคุณเข้ามาตรฐานส่งออกหรือจับข้อผิดพลาดกับฟังก์ชัน Win32 นอกจากนี้ยังเป็นเรื่องเล็กน้อยที่จะเปลี่ยนเส้นทางสตรีมมาตรฐานของกระบวนการ [เด็ก] ที่มีการวางไข่ด้วย. NET ซึ่งฉันเชื่อว่าการแมปไปยังฟังก์ชั่น Win32 (แต่ฉันไม่แน่ใจ 100% - ฉันไม่ใช่ Win32 dev)
Bob

1
อานี่ 's เทียบเท่า Win32 โดยการตั้งค่าพารามิเตอร์ที่เหมาะสมในSTARTUPINFOstruct CreateProcess()สำหรับ
Bob

27

หากคุณพอใจกับการเปลี่ยนเส้นทางเอาต์พุตและอินพุตคำอธิบายนั้นค่อนข้างง่าย

Command1 | Command2

ทำเช่นเดียวกัน

Command1 > tempfile
Command2 < tempfile

tempfileแต่ไม่มี เอาต์พุตของCommand1เชื่อมต่อโดยตรงกับอินพุตCommand2และการถ่ายโอนเกิดขึ้นในหน่วยความจำ


ฉันอาจจะผิด แต่ฉันคิดว่า tempfile มีอยู่แม้ในไวยากรณ์ของไปป์ มันไม่มีชื่อ
Taemyr

3
ไม่มันทำไม่ได้ ไม่มีการดำเนินการของระบบไฟล์ที่เกี่ยวข้องเมื่อไพพ์เอาต์พุตจากคำสั่งหนึ่งไปยังอินพุตของคำสั่งอื่น
Daniel B

1
แม้ว่าภายใต้ DOS (และ Windows ส่วนใหญ่เป็นไปได้) ไฟล์ชั่วคราวถูกสร้างขึ้นโดยไปป์ ไม่ใช่ * ระวัง แต่ก็ไม่คุ้มค่ากับความแตกต่าง
Jeremy J Starcher

ฉันค่อนข้างมั่นใจว่านี่ไม่ถูกต้อง รายงานกระบวนการตรวจสอบไม่มีCreateFileหรือWriteFileโทรไปสำรองเรียกร้องของคุณ / edit: แน่นอนว่าสำหรับส่วน Windows แน่นอน
Daniel B

3

จริง ๆ ถ้าคุณต้องการทราบว่าไปป์ทำอะไรและความแตกต่างระหว่าง> และ | จากนั้นไปที่ไดเรกทอรีที่มีไฟล์จำนวนมากและ

จาก terminal ls vs ls | more (หรือทำสิ่งนั้นจาก Windows ด้วย DIR และ DIR | เพิ่มเติม)

หากคุณใช้มากกว่านั้นคุณจะเห็นว่ามันสร้างไฟล์ชื่อ 'มากกว่า' แทนที่จะส่งเอาต์พุตของ ls ไปยังคำสั่ง 'more' ดังนั้นถ้ามีคนทำมากกว่านี้มันอาจจะเป็นความผิดพลาดอย่างใดอย่างหนึ่งไม่ได้ทำ> มากกว่าที่คุณทำ> file1 เพิ่มเติมเป็นคำสั่งที่รู้จักกันดี

<like the> ใช้สำหรับเชื่อมโยงคำสั่งและไฟล์แทนที่จะใช้คำสั่งกับคำสั่ง แต่ในขณะที่> ส่งเอาต์พุตของคำสั่งไปยังไฟล์ <ส่งไฟล์เป็นอินพุตไปยังคำสั่ง ฉันไม่ค่อยใช้ <เพราะฉันมักจะใช้ cat file1 | เพื่อส่งออกไฟล์ไปยังคำสั่ง

$ grep a <file1 abc

$ cat file1 | grep a abc

grep พร้อมพารามิเตอร์ 2 ตัวเป็นไฟล์รูปแบบ grep pattern grep ที่มีหนึ่งพารามิเตอร์คือรูปแบบ grep และคุณสามารถส่งไฟล์โดยการไพพ์เนื้อหาของไฟล์หรือโดยใช้ < หากใช้ <คุณเขียนชื่อคำสั่งก่อนจากนั้นจึงใช้ชื่อไฟล์หลังจากนั้นให้ใช้คำสั่ง <ไฟล์ หากใช้ | เพื่อไพพ์เนื้อหาของไฟล์คุณใช้ cat file1 | คำสั่ง

คำสั่งจำนวนมากยังใช้ไฟล์เป็นอินพุตดังนั้น grep ที่ file1 จะทำงานเช่นเดียวกับ cat file1 | grep a และ grep a <file1

ฉันกำลังทำ pipes (|) และ> บน DOS เมื่อ 15 ปีก่อน

เพื่อสรุปวิธีการ แตกต่างจาก <และ> - ไปป์อยู่ระหว่าง 2 คำสั่ง <และ> นั่งระหว่างคำสั่งและไฟล์ > คือส่งออกไปยังไฟล์ <คืออินพุตจากไฟล์


3

ไพพ์อักขระ ( |) เชื่อมต่อเอาต์พุตของโปรแกรมหนึ่งไปยังอินพุตของอีกโปรแกรมหนึ่ง

ในตัวอย่างนี้echoพิมพ์คำhelloและwc -cนับจำนวนอักขระของอินพุต:

echo hello | wc -c

ฉันคิดว่าคุณควรพูดในทันทีที่เสียงสะท้อนนั้นจะออก "hello \ n" คุณไม่ได้บอก OP เพื่อศึกษาคุณกำลังบอกเรื่องนี้กับทุกคนที่อ่านคำตอบของคุณ ทำไมทวีคูณเสียเวลาเปล่า
Rodrigo

ขอบคุณสำหรับคำติชมฉันทำให้คำตอบของฉันสั้นลง
bbaassssiiee

2

เพื่อที่จะเข้าใจสิ่งนี้ลองด้วยตัวคุณเอง:

sort -r

ตอนนี้คุณกำลังแขวนด้วยเคอร์เซอร์และมันก็ไม่ได้ทำอะไรเลย จะเกิดอะไรขึ้นถ้าคุณพิมพ์ข้อมูลบางอย่าง

1
2
3
5
4

ยังไม่มีอะไรใช่มั้ย ตอนนี้กด ctrl + D

5
4
3
2
1

ดังนั้นการเรียงลำดับจะใช้อินพุต (สิ่งที่คุณพิมพ์) ทำบางสิ่งกับมัน (เรียงลำดับ) และให้กลับเป็นเอาต์พุต lsคำสั่งไม่ได้ใช้การป้อนข้อมูลก็เพียงสร้างผลลัพธ์ สัญลักษณ์ไปป์รับเอาต์พุตจากlsและฟีดมันเป็นอินพุตไปยังsortคำสั่ง

>ไม่ฟีดเอาต์พุตไปยังโปรแกรม แต่เก็บเอาท์พุทเป็นไฟล์ <ใช้ไฟล์เป็นอินพุต

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