Bash: วิธีอ่านทีละหนึ่งบรรทัดจากเอาต์พุตของคำสั่ง?


49

while loopฉันพยายามที่จะอ่านผลลัพธ์ของคำสั่งในทุบตีใช้ที่

while read -r line
do
    echo "$line"
done <<< $(find . -type f)

ผลลัพธ์ที่ฉันได้รับ

ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$ 

หลังจากนี้ฉันก็ลอง

$(find . -type f) | 
while read -r line
do
    echo "$line"
done 

test.sh: line 5: ./test.py: Permission deniedแต่มันก็สร้างข้อผิดพลาด

ดังนั้นฉันจะอ่านทีละบรรทัดได้อย่างไรเพราะฉันคิดว่าขณะนี้มันกำลังซัดทั้งบรรทัดในครั้งเดียว

เอาต์พุตที่ต้องการ:

./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello

3
ฉันขอแนะนำให้อ่านBash คำถามที่พบบ่อย 01 - ข้อมูลที่เป็นประโยชน์มากมายและคำแนะนำเกี่ยวกับกับดักเพื่อหลีกเลี่ยง
jw013

สำหรับwhile readส่วนนี้ให้ดูที่การทำความเข้าใจกับ IFSและคำถามที่เชื่อมโยงอยู่ที่นั่น
Gilles 'หยุดความชั่วร้าย'

คำตอบ:


54

มีข้อผิดพลาดคุณ< <(command)ไม่จำเป็น<<<$(command)

< <( )เป็นชดเชยกระบวนการ , $()เป็นแทนคำสั่งและ<<<เป็นที่นี่สตริง


2
@RanRag หยุดพยายามใส่$( )ทุกอย่าง! นั่นคือไวยากรณ์สำหรับการทดแทนคำสั่งซึ่งเป็นวิธีเดียวเท่านั้นที่จะใช้เอาต์พุตคำสั่ง การทดแทนไพพ์และกระบวนการและที่นี่คือสตริงอื่นและทั้งหมดนั้นมีไวยากรณ์ที่แตกต่างกันตามธรรมชาติ คุณไม่ควรแยกชื่อไฟล์ต่อไปจนกว่าคุณจะรู้ว่าคุณกำลังทำอะไรอยู่
jw013

Process Substitutionขอบคุณมันทำงานจะอ่านเพิ่มเติมเกี่ยวกับ
RanRag

@ jw013: ฉันเริ่มต้นทุบตี ในอนาคตจะทำให้ข้อเสนอแนะของคุณอยู่ในใจของฉัน
RanRag

13

โปรดทราบว่าไม่มีการหยุดชื่อไฟล์จากการมีอักขระขึ้นบรรทัดใหม่ วิธี canonical เพื่อรันคำสั่งสำหรับแต่ละไฟล์ที่พบโดย find คือ

find . -type f -exec cmd {} \;

และถ้าคุณต้องการสิ่งที่ทำในทุบตี:

find . -type f -exec bash -c '
  for file do
    something with "$file"
  done' bash {} +

นอกจากนี้วิธีที่เป็นที่นิยมในการเรียกคำสั่ง "อ่าน" ในสคริปต์ (ถ้าคุณไม่ต้องการให้มันประมวลผลเพิ่มเติมในอินพุต) คือ:

IFS= read -r var

-rคือการหยุดreadการรักษาอักขระแบ็กสแลชเป็นพิเศษ (เป็นอักขระยกเว้นสำหรับตัวคั่นและบรรทัดใหม่) และ IFS = เพื่อตั้งค่ารายการของตัวคั่นเป็นสตริงว่างสำหรับread(มิฉะนั้นถ้าอักขระช่องว่างอยู่ในรายการนั้นพวกเขาจะถูกปล้นจาก จุดเริ่มต้นและจุดสิ้นสุดของอินพุต)

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

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