Как мне обработать список файлов с пробелами в именах в Unix? - PullRequest
4 голосов
/ 28 декабря 2008

Я пытаюсь перечислить файлы в каталоге и что-то с ними сделать в приглашении Mac OS X.

Должно быть так: для f в $ (ls -1); сделать эхо $ F; сделано

Если у меня есть файлы без пробелов в именах (fileA.txt, fileB.txt), эхо работает нормально. Если файлы содержат пробелы в своих именах («файл A.txt», «файл B.txt»), я получаю 4 строки (файл, A.txt, файл, B.txt).

Я пытался процитировать команду листинга, но это только изменило проблему.

Если я сделаю это: для f в $ (ls -1); сделать эхо $ F; сделанный Я получаю: файл A.txt \ nfile B.txt

(отображается правильно, но это одна строка, и мне нужно разделить две строки.

Ответы [ 6 ]

12 голосов
/ 28 декабря 2008

Отойдите от ls, если это вообще возможно. Используйте find из пакета findutils.

find /target/path -type f -print0 | xargs -0 your_command_here

-print0 заставит find выводить имена, разделенные символами NUL (ноль ASCII). Аргумент -0 для xargs говорит, что он также должен ожидать аргументы, разделенные символами NUL, поэтому все будет работать нормально.

Замените /target/path на путь, по которому находятся ваши файлы.

-type f будет искать только файлы. Используйте -type d для каталогов или вообще опустите, чтобы получить оба.

Замените your_command_here командой, которую вы будете использовать для обработки имен файлов. (Примечание: если вы запустите это из оболочки, используя echo для your_command_here, вы получите все в одну строку - не запутайтесь в этом артефакте оболочки, xargs все равно сделает ожидаемую правильную вещь.)

Редактировать: В качестве альтернативы (или если у вас нет xargs), вы можете использовать гораздо менее эффективный

find /target/path -type f -exec your_command_here \{\} \;

\{\} \; является экранированием для {} ;, который является заполнителем для текущего обработанного файла. Затем find вызовет your_command_here с заменой {} ; на имя файла, и, поскольку your_command_here будет запущен командой find, а не оболочкой, пробелы не будут иметь значения.

Вторая версия будет менее эффективной, так как find запустит новый процесс для каждого найденного файла. xargs достаточно умен, чтобы перенаправить команды во вновь запущенный процесс, если сможет понять, что это безопасно. Предпочитаю версию xargs, если у вас есть выбор.

10 голосов
/ 28 декабря 2008
for f in *; do echo "$f"; done

должен делать то, что вы хотите. Почему вы используете ls вместо *?

В общем, работа с пробелами в оболочке - это PITA. Взгляните на переменную $IFS, а еще лучше на Perl, Ruby, Python и т. Д.

2 голосов
/ 28 декабря 2008

Вот ответ с использованием $ IFS, как обсуждено derobert http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html

0 голосов
/ 06 января 2009

look - опция стиля цитирования. например, --quoting-style = c выдаст:

$ ls --quoting-style = c

"file1" "file2" "dir one"

0 голосов
/ 28 декабря 2008

Вы можете передать аргументы в read. Например, чтобы cat все файлы в каталоге:

ls -1 | while read FILENAME; do cat "$FILENAME"; done

Это означает, что вы все равно можете использовать ls, как у вас в вопросе, или любую другую команду, которая выводит $IFS с разделителями.

Цикл while значительно упрощает выполнение нескольких действий с аргументом и, по моему мнению, делает сложную обработку более читабельной. Придуманный пример:

ls -1 | while read FILE
do
    echo 1: "$FILE"
    echo 2: "$FILE"
done
0 голосов
/ 28 декабря 2008

Проверьте справочную страницу для xargs:

работает так:

ls -1 /tmp/*.jpeg | xargs rm

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...