วิธีการผสานและไพพ์เป็นผลมาจากคำสั่งที่แตกต่างกันสองคำสั่งเป็นคำสั่งเดียว


34

ฉันต้องการผสาน (ยูเนี่ยน) เอาท์พุทจากสองคำสั่งที่แตกต่างกันและไพพ์พวกเขาไปที่คำสั่งเดียว

ตัวอย่างโง่ ๆ :

คำสั่งที่ฉันต้องการรวมเอาท์พุท:

cat wordlist.txt
ls ~/folder/*

เป็น:

wc -l

ในตัวอย่างนี้ถ้า wordlist.txt มี 5 บรรทัดและ 3 ไฟล์ฉันต้องการwc -lส่งคืน 8

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8

ฉันจะทำอย่างไร

คำตอบ:


55

สิ่งมหัศจรรย์สหภาพของคุณคืออัฒภาค ... และวงเล็บปีกกา:

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l

วงเล็บปีกกาเป็นเพียงการจัดกลุ่มคำสั่งเข้าด้วยกันเพื่อให้ป้ายไปป์|มีผลต่อเอาต์พุตรวม

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

    cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
    cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd

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

สำหรับเซมิโคลอนตัวเลือกรวมถึง&&และ||เครื่องหมายซึ่งจะดำเนินการตามคำสั่งที่มีเงื่อนไขเฉพาะในกรณีที่เป็นครั้งแรกที่ประสบความสำเร็จหรือไม่ตามลำดับเช่น

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."

1
มันใช้งานได้! ช่วยฉันเรียนรู้ - วงเล็บปีกกากำลังทำอะไรที่นี่? พวกเขามีพลังเวทมนต์อะไรอีกบ้าง?
David Oneill

@DavidOneill { list; }เป็นคำสั่งผสม จากbash(1): รายการถูกเรียกใช้งานในสภาวะแวดล้อมเชลล์ปัจจุบัน รายการจะต้องถูกยกเลิกด้วยการขึ้นบรรทัดใหม่หรืออัฒภาค [.. ] สถานะการส่งคืนคือสถานะการออกของรายการ
Lekensteyn

ฉันได้เพิ่มข้อมูลอีกเล็กน้อยในคำตอบ คำแนะนำที่ชัดเจนสำหรับเชลล์สคริปต์ด้วย bash คือ bash manpage พิมพ์man bashจากบรรทัดคำสั่งและเรียกดู
pablomme

ควร; ในคำสั่งเหล่านั้นไม่ใช่ && ในกรณีที่ไฟล์ wordlist.txt ไม่มีอยู่จริง?
Rinzwind

หากwordlist.txtไม่มีข้อผิดพลาดจากcatจะปรากฏในข้อผิดพลาดมาตรฐาน แต่ไม่ได้อยู่ในเอาต์พุตมาตรฐานดังนั้นwc -lจะไม่นับบรรทัดใด ๆ จากมัน กันไปสำหรับ~/folderไม่ได้มีอยู่ หนึ่งสามารถเพิ่ม2> /dev/nullระหว่างแต่ละคำสั่งเหล่านี้และอัฒภาคของพวกเขาเพื่อป้องกันเสียงรบกวนจากข้อผิดพลาดมาตรฐาน แต่นอกเหนือจากการน่าเกลียดข้อความผิดพลาดจะไม่เป็นอันตรายสำหรับวัตถุประสงค์ในการนับบรรทัด
pablomme

8

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

wc -l <(cat wordlist.txt; ls ~/folder/*)

สิ่งนี้เทียบเท่ากับ:

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp

โปรดทราบว่าls ~/folder/*จะส่งคืนเนื้อหาของไดเรกทอรีย่อยหากมี (เนื่องจากการขยายแบบ glob) ถ้าคุณเพียงต้องการที่จะแสดงรายการเนื้อหาของการใช้งานเพียงแค่~/folderls ~/folder


นี่wc -lเป็นเพียงตัวอย่างที่สร้างขึ้นจริง ๆ แล้วฉันกำลังนำไปวางในสิ่งที่ซับซ้อนกว่าซึ่งไม่มีตัวเลือกนี้
David Oneill

2
@DavidOneill ดีที่catได้รับการพิสูจน์ไฟล์ที่คุณสามารถใช้และแม้กระทั่งcat <(cat wordlist.txt; ls wordlist.txt) | wc -l cat wordlist.txt <(ls wordlist.txt) | wc -lแน่นอนว่ามันน่าเกลียดมาก แต่มันแสดงให้เห็นถึงความเป็นไปได้ที่ไม่มีที่สิ้นสุดด้วยเครื่องมือบรรทัดคำสั่ง
Lekensteyn

1
@DavidOneill ถูกต้องฉันได้แก้ไขทันทีขอบคุณ
Lekensteyn

1
คุณต้องการls ~/folder/เพื่อที่ว่าถ้า~/folderเป็นลิงค์สัญลักษณ์lsแสดงเนื้อหาของเป้าหมายแทนที่จะเป็นลิงค์เอง โดยวิธีการlsคำสั่งทั้งหมดควรจะตามด้วย-1เพื่อให้ไฟล์เดียวต่อบรรทัดถูกพิมพ์และwc -lเป็นวิธีที่ถูกต้องของการนับไฟล์
pablomme

@pablomme คุณจริงเกี่ยวกับสิ่ง symlink แต่-1ส่อให้เห็นว่าการส่งออกไม่ได้เป็นสถานี แต่ท่อ
Lekensteyn

2

ฉันถามตัวเองด้วยคำถามเดียวกันและจบลงด้วยการเขียนบทสั้น ๆ

magicalUnionThing(ฉันเรียกมันว่าappend):

#!/bin/sh
cat /dev/stdin
$*

ทำให้สคริปต์นั้นทำงานได้

chmod +x ./magicalUnionThing

ตอนนี้คุณทำ

cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l

มันทำอะไร:

  • ส่งอินพุตมาตรฐานไปยังเอาต์พุตมาตรฐาน
  • ดำเนินการโต้แย้ง $*ส่งคืนอาร์กิวเมนต์ทั้งหมดเป็นสตริง เอาต์พุตของคำสั่งนั้นจะไปที่เอาต์พุตสคริปต์มาตรฐานโดยค่าเริ่มต้น

ดังนั้น stdout ของ magicalUnionThing จะเป็น stdin + stdout ของคำสั่งที่ถูกส่งเป็นอาร์กิวเมนต์

แน่นอนมีวิธีที่ง่ายกว่าตามคำตอบอื่น ๆ
บางทีตัวเลือกนี้อาจมีประโยชน์ในบางกรณี

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