Как я могу обработать результаты поиска в bash-скрипте? - PullRequest
56 голосов
/ 18 января 2010

Я пытаюсь использовать массив для хранения списка имен файлов с помощью команды find.

По какой-то причине массив не работает в bash, используемом в школе, хотя моя программа работает на моем ноутбуке.

Так что мне было интересно, есть ли другой способ сделать это, вот что у меня есть:

array = (`find . -name "*.txt"`)  #this will store all the .txt files into the array

Затем я могу получить доступ к элементам массива и сделать копии всех файлов с помощью команды cat.

Есть ли другой способ сделать это без использования массива?

Ответы [ 5 ]

108 голосов
/ 18 января 2010

Вы можете использовать что-то вроде этого:

find . -name '*.txt' | while read line; do
    echo "Processing file '$line'"
done

например. сделать копию:

find . -name '*.txt' | while read line; do
    echo "Copying '$line' to /tmp"
    cp -- "$line" /tmp
done

НТН

18 голосов
/ 16 июня 2012

У меня была проблема с решением Йоханнеса Вайса, если бы я просто делал эхо, это работало бы для полного списка файлов. Однако, если бы я попытался запустить ffmpeg на следующей строке, скрипт обработал бы только первый файл, с которым столкнулся. Я предположил что-то смешное из-за IFS из-за несоответствия, но не смог разобраться и запустил цикл for:

for i in $(find . -name '*.mov' ); 
do
    echo "$i"
done
7 голосов
/ 12 марта 2011

Только не ставьте пробелы вокруг знака равенства:

ar=($(find . -name "*.txt"))

По возможности избегайте обратных кавычек, поскольку они устарели. Их можно легко спутать с апострофом, особенно в бедных шрифтах, и они не очень хорошо вкладываются.

В большинстве случаев вам будет лучше обслуживаться, если вы итерируете результаты поиска напрямую с помощью -exec, -execdir, -ok или -okdir.

Циклы For и while трудно сделать правильно, когда дело доходит до пробелов в именах файлов, новых строках и вкладках.

find ./ -name "*.txt" -exec grep {} ";"

{} не нуждается в маскировке. Вы часто будете видеть комбинацию find / xargs, которая также запускает дополнительный процесс:

find ./ -name "*.txt" | xargs grep {} ";"
5 голосов
/ 11 апреля 2018

Я думаю, что у starpause самое чистое решение, но оно терпит неудачу, когда в путях есть пробелы. Это исправлено установкой IFS. Правильный ответ поэтому:

IFS=$'\n'
for i in $(find . -name '*.mov' ); 
do
    echo "$i"
done
unset IFS

Вы сбросили IFS, чтобы сбросить поведение для IFS и узнать, почему $ необходим в IFS=$'\n', см. https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting

3 голосов
/ 18 января 2010
find . -name '*.txt' | while IFS= read -r FILE; do
    echo "Copying $FILE.."
    cp "$FILE" /destination
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...