используя "ls" и сохраняя пробелы в результирующем массиве - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь прочитать каталог с помощью "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

Как я могу сохранить пробелы в "файлах = (` ls -1`) "?

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Не.

См .:


Если это вообще возможно, используйте вместо этого глобус оболочки.

То есть:

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, сетевого потока или другого уровня удаленного взаимодействия (при условии, что подобная сложность не позволяет использовать собственный глобус оболочки).

0 голосов
/ 12 февраля 2019

Кажется, главный вывод не использовать 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> t".Затем (выявление других проблем с 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
0 голосов
/ 12 февраля 2019

Попробуйте это:

eval files=($(ls -Q))

Опция -Q включает цитирование имен файлов.Опция -1 подразумевается (не требуется), если вывод не является tty.

...