Bash: Як читати по одному рядку одночасно з виводу команди?


49

Я намагаюся прочитати вихід команди в bash за допомогою 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 і питання , пов'язані там.
Жил "ТАК - перестань бути злим"

Відповіді:


54

Там це помилка, вам потрібно < <(command)НЕ<<<$(command)

< <( )є Заміна процесу , $()це підміна команд і <<<є рядок тут .


2
@RanRag Перестань намагатися $( )все навколо! Це синтаксис заміни команд , який є лише одним із способів використання виводу команд. Труби та процес заміщення і тут-рядки - це інші, і всі вони мають різний синтаксис, природно. Ви ні в якому разі не повинні розбирати імена файлів, якщо ви дійсно не знаєте, що робите.
jw013

Дякуємо, що це працювало, читайте докладніше Process Substitution.
RanRag

@ jw013: Я початківець баш. Надалі я буду тримати вашу думку в думці.
RanRag

13

Зауважте, що ніщо не зупиняє імена файлів, що містять символи нового рядка. Канонічним способом запуску команди для кожного файлу, знайденого методом find, є.

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

І якщо ви хочете, щоб справи були зроблені в баш:

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

Крім того, канонічним способом викликати команду "read" у скриптах (якщо ви не хочете, щоб вона додатково обробляла вхід):

IFS= read -r var

-rполягає в тому, щоб зупинитись readіз особливою обробкою символів зворотної косої риси (як символ бігу для роздільників та нового рядка), а IFS = встановити список роздільників для порожнього рядка read(інакше, якщо який-небудь символ пробілу був у цьому списку, вони будуть зняті з початок і кінець вводу).

Використання циклів у оболонках зазвичай погана ідея (не про те, як це робиться в оболонках, коли ви змушуєте кілька інструментів працювати колективно і одночасно над завданням, а не виконувати один чи кілька інструментів сотні разів послідовно).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.