Захват результатов поиска. -print0 в массив bash - PullRequest
72 голосов
/ 13 июля 2009

Использование find . -print0 представляется единственным безопасным способом получения списка файлов в bash из-за возможности имен файлов, содержащих пробелы, символы новой строки, кавычки и т. Д.

Тем не менее, мне трудно на самом деле сделать вывод find полезным в bash или с другими утилитами командной строки. Единственный способ, которым мне удалось использовать вывод, - это передать его в perl и изменить IFS в perl на null:

find . -print0 | perl -e '$/="\0"; @files=<>; print $#files;'

В этом примере печатается количество найденных файлов, что исключает опасность появления новых строк в именах файлов, приводящих к искажению счетчика, как это происходит с:

find . | wc -l

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

Как я могу это сделать?

Это не работает:

find . -print0 | ( IFS=$'\0' ; array=( $( cat ) ) ; echo ${#array[@]} )

Гораздо более общий вопрос: Как я могу делать полезные вещи со списками файлов в bash?

Ответы [ 13 ]

0 голосов
/ 13 февраля 2016

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

savedFS="$IFS"
IFS=$'\x3'
filenames=(`find wherever -printf %p$'\x3'`)
IFS="$savedFS"
0 голосов
/ 06 января 2013

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

Я бы рекомендовал использовать python с библиотекой sh .

0 голосов
/ 13 июля 2009

Это похоже на версию Stephan202, но файлы (и каталоги) помещаются в массив сразу. Цикл for здесь просто для того, чтобы «делать полезные вещи»:

files=(*)                        # put files in current directory into an array
i=0
for file in "${files[@]}"
do
    echo "File ${i}: ${file}"    # do something useful 
    let i++
done

Чтобы получить счет:

echo ${#files[@]}
...