Используя "ls" и сохраняя пробелы в результирующем массиве
Я пытаюсь прочитать каталог с "ls" и выполнить операции на нем
Пример каталога:
$ ls -1
x x
y y
z z
файл сценария: myScript.sh
#!/bin/bash
files=(`ls -1`);
for ((i=0; i<"${#files[@]}"; i+=1 )); do
echo "${files[$i]}"
done
Тем не менее, выход
$ myScript.sh
x
x
y
y
z
z
пока, если я определю "файлы" следующим образом
$ files=("x x" "y y" "z z")
$ for ((i=0; i<"${#files[@]}"; i+=1 )); do echo "${files[$i]}"; done
x x
y y
z z
Как я могу сохранить пробелы в "files=(`ls -1`)"?
3 ответа
Не.
Увидеть:
Если это вообще возможно, используйте вместо этого оболочку.
То есть:
files=( * )
Если вам нужно представить имена файлов в виде потока текста, используйте разделители NUL.
То есть либо:
printf '%s\0' *
или же
find . -mindepth 1 -maxdepth 1 -print0
выдаст строку, разделенную NUL, которую вы можете безопасно загрузить в массив оболочки, используя (в современном bash 4.x):
readarray -d '' array < <(find . -mindepth 1 -maxdepth 1 -print0)
... или для поддержки bash 3.x:
array=( )
while IFS= read -r -d '' name; do
array+=( "$name" )
done < <(find . -mindepth 1 -maxdepth 1 -print0)
В любом из вышеперечисленных find
команда может находиться на другой стороне FIFO, сетевого потока или другого уровня удаленного взаимодействия (при условии, что такая сложность не позволяет использовать встроенный глобус оболочки).
Кажется, главный вывод не использовать ls
, Еще в плейстоценовом веке программирования Unix они использовали ls
; Однако в эти дни ls
лучше всего ограничивается производством только для чтения человеком. Надежный сценарий для всего, что может быть добавлено в ваш сценарий (конечные строки, пробелы, китайские иероглифы, смешанные с ивритом и французским языком и т. Д.), Лучше всего достигается с помощью какой-либо формы сглаживания (как рекомендовано другими здесь BashPitfalls).
#!/bin/bash
for file in ./*; do
[ -e "${file}" ] || continue
# do some task, for example, test if it is a directory.
if [ -d "${file}" ]; then
echo "${file}"
fi
done
./
Возможно, это не является абсолютно необходимым, но это может помочь, если файл начинается с "-", уточняя, какой файл имеет строку возврата (или строки), и, вероятно, некоторые другие неприятные ошибки. Это также полезный шаблон для определенных файлов (.eg, ./*.pdf
). Например, предположим, что в вашем каталоге находятся следующие файлы: "-t" и " <CR>
т ". Затем (выявление других проблем с ls
при использовании нестандартных символов)
$ ls
-t ?t
$ for file in *; do ls "${file}"; done
-t ?t
?t
в то время как:
$ for file in ./*; do ls "${file}"; done
./-t
./?t
также
$ for file in ./*; do echo "${file}"; done
./-t
./
t
Обходной путь с помощью команд POSIX может быть достигнут --
$ for file in *; do ls -- "${file}"; done # work around
-t
?t
Попробуй это:
eval files=($(ls -Q))
вариант -Q
позволяет цитирование имен файлов. вариант -1
подразумевается (не требуется), если вывод не tty.