Я просто хочу получить все файлы в определенном каталоге в массив bash (при условии, что ни один из файлов не имеет новой строки в имени):
Так:
myarr=()
find . -maxdepth 1 -name "mysqldump*" | mapfile -t myarr; echo "${myarr[@]}"
Пустой результат!
Если я делаю окольный способ использования файла, временного или иного:
myarr=()
find . -maxdepth 1 -name "mysqldump*" > X
mapfile -t myarray < X
echo "${myarray[@]}"
Результат!
Но почему не mapfile
читает правильно из трубы?
find
иmapfile
здесь вообще, а не простоmyarr=(mysqldump*)
? Это будет работать даже с именами файлов с пробелами и символами новой строки.nullglob
параметр (shopt -s nullglob
),myarr=(mysqldump*)
чтобы не заканчивать массив('mysqldump*')
в случае, если файлы не совпадают.Ответы:
От
man 1 bash
:Такие подоболочки наследуют переменные из основной оболочки, но они независимы. Это означает, что
mapfile
в вашей исходной команде действует самостоятельноmyarr
. Затемecho
(находясь вне трубы) печатает пустойmyarr
(который является основной оболочкойmyarr
).Эта команда работает по-другому:
В этом случае
mapfile
иecho
работают одинаковоmyarr
(что не является основной оболочкойmyarr
).Чтобы изменить основную оболочку,
myarr
вы должныmapfile
точно запустить основную оболочку. Пример:источник
Bash запускает команды конвейера в среде подоболочек, поэтому любые переменные и т. Д., Которые происходят внутри него, не видны остальной части оболочки.
Dash (Debian
/bin/sh
) и busyboxsh
похожи, в то время как zsh и ksh выполняют последнюю часть в основной оболочке. В Bash вы можете использоватьshopt -s lastpipe
то же самое, но это работает только тогда, когда управление заданиями отключено, поэтому по умолчанию не используется в интерактивных оболочках.Так:
(
read
иmapfile
имеют ту же проблему.)В качестве альтернативы (и как уже упоминалось в Attie), используйте процесс подстановки , который работает как обобщенный канал и поддерживается в Bash, ksh и zsh.
POSIX оставляет это неопределенным, если части конвейера работают в подоболочках или нет, так что нельзя сказать, что какая-либо из оболочек будет «неправильной» в этом.
источник
set +m; shopt -s lastpipe; x=a; echo b | read x; echo $x; set -m
Как отметил Камиль, каждый элемент в конвейере - это отдельный процесс.
Вы можете использовать следующую подстановку процесса для
find
запуска в другом процессе сmapfile
вызовом, оставшимся в вашем текущем интерпретаторе, позволяющемmyarr
впоследствии доступ к :b < <( a )
будет действовать аналогично сa | b
точки зрения того, как конвейер подключен - разница в том, чтоb
выполняется « здесь ».источник