Intereting Posts
Как я могу получить номера страниц только шаблона в файле PDF, независимо от того, является ли шаблон многострочным? Прочитайте, но не записывайте доступ к сокету в Linux, что можно сделать с этим? Где я могу найти драйвер Linux для наушников в дереве ядра? «Ошибка получения подписи сертификата сертификата ошибки» при объединении сертификатов в хранилище ключей PKCS12 gui для подрывной работы с kde (kdesvn?) GNU Parallel: как сохранить результаты нескольких команд для переменной? Сбой Ethernet-порта Asus F556U и Wifi нестабильны Прокси-сервер SSH Почему по умолчанию используется swappiness? Два сетевых адаптера с DHCP, используйте один в качестве резервного file-roller: произошла ошибка при загрузке архива (Zip / 7z) Рассмотрение группы и пользователя для установки Apache httpd с другим каталогом – CentOS 6.6 Как создать нового пользователя, но с уже существующим домашним каталогом? Как правильно изменить отображение клавиатуры? LVM держит жесткий диск?

Bash: вывод трубы «find» в «readarray»

Я пытаюсь найти файлы с помощью find и помещать эти файлы в массив Bash, чтобы я мог выполнять другие операции над ними (например, ls или grep ). Но я не могу понять, почему readarray не читает вывод вывода, поскольку он подключен к нему.

Скажем, у меня есть два файла в текущем каталоге: file1.txt и file2.txt . Таким образом, вывод find выглядит следующим образом:

 $ find . -name "file*" ./file1.txt ./file2.txt 

Поэтому я хочу "./file1.txt" это в массив, чьи два элемента являются строками "./file1.txt" и "./file2.txt" (без кавычек, очевидно).

Я пробовал это, среди нескольких других вещей:

 $ declare -a FILES $ find . -name "file*" | readarray FILES $ echo "${FILES[@]}"; echo "${#FILES[@]}" 0 

Как видно из вывода echo , мой массив пуст.

Итак, что именно я делаю неправильно здесь? Почему readarray не считывает вывод find качестве стандартного ввода и помещает эти строки в массив?

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

Использовать замену процесса:

 readarray FILES < <(find) 

Обратите внимание, что он не работает для файлов с символами новой строки в их именах.

Правильное решение:

 unset a; declare -aa while IFS= read -r -u3 -d $'\0' file; do a+=( "$file" ) # or however you want to process each file done 3< <(find /tmp -type f -print0) 

Это похоже на то, что подробно объясняет Greg's BashFAQ 020, и этот ответ охватывает .

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

readarray также может читать из stdin

 readarray FILES <<< "$(find . -name "file*")"; echo "${#FILES[@]}"