2013-04-01 4 views
2

Я начинаю скрипты bash, и я не могу обрабатывать заданное имя файла. Я искал другие вопросы о моей проблеме здесь, как:Понимание (множественное и автоматическое) имя файла, цитируемое

how to output file names surrounded with quotes in SINGLE line?

В моем сценарии я должен принять все directorys, конец для каждого из них делать какую-то работу. Таким образом, скелет моего сценария:

for directory in `find "$DIR" -type d` 
do 
# ... some work ... 
done 

Этот скрипт не работает с разнесенным именем файла. Поэтому я попытался использовать find в сочетании с exec, что кажется элегантным и простым решением, но ничего не изменилось. Точнее я попробовал:

(I) find "$DIR" -type d -exec echo -n '"{}" ' \; 
(II) find "$DIR" -type d -exec echo -n '"{}" ' + 

Перед использованием команды -exec я прочитал что-то об этом, но что-то до сих пор не ясно для меня, так:

  1. Что и как работает «{}" '\;
  2. Что и как работает? "{}" '+
  3. Как я могу исправить свой скрипт также для разнесенного имени файла?
+2

См. Предыдущие ответы [здесь] (http://stackoverflow.com/questions/7039130/bash-iterate-over-list-of-files-with-spaces#7039579) и [здесь] (http: // stackoverflow .com/вопросы/1116992/захватывая-выход-оф-найти-print0-в-а-баш-массива # 1120952). –

+0

Ссылки @GordonDavisson содержат ответы на вашу проблему. Просто прочитайте это. –

ответ

1

Это может работать лучше для вас:

while IFS= read -r adir ; do 
    echo "Directory: $adir" 
done < <(find "$DIR" -type d) 
+0

Ошибка, если имя каталога начинается с пробелов или содержит обратную косую черту или символы новой строки, а другая версия эха будет вести себя по-разному с разными настройками $ adir. Всегда используйте 'IFS = read -r', если у вас нет особых причин не знать и точно знать, что такое последствия. –

+0

Хорошие моменты, но позвольте мне сказать, что вы работаете с довольно испорченными именами файлов (через 30 лет я никогда не сталкивался с новой строкой в ​​имени файла - backspaces, конечно, например, с помощью секретного файла AppleDOS). Кроме того, эхо, очевидно, является заполнителем. – William

+0

К сожалению, на работе мы используем CMS с именем SVN, который автоматически автоматически создает файлы резервных копий, содержащие новые строки в своих именах, так что это то, с чем мы имеем дело ... –

1

я использую этот формат & он работает отлично:

find '/path/to/directories' -type d |\ 
    while read DIRNAME 
    do 
    echo "${DIRNAME}" 
    done 
+0

Не удалось, если имя каталога начинается с пробелов или содержит обратную косую черту или символы новой строки, а другая версия эха будет вести себя по-другому с различными настройками $ adir. Всегда используйте 'IFS = read -r', если у вас нет особых причин не знать и точно знать, что такое последствия. –

2

Что и как работает '{} "' \;

Для каждого файла, это будет в основном выполнять echo -n "\"filename\" ", создавая кучу линий, как "filename".

Добавление буквенных котировок не помогает, потому что bash не запускает интерпретацию данных как код сценария оболочки.

Если вы используете read foo; ls $foo, вы можете просто ввести $(rm /), чтобы выполнить команду, и вы не можете просто ввести "foo bar", чтобы избежать разделения имени файла. Данные - это данные, а не код, а синтаксис оболочки не соблюдается.

Что и как работает «{}"»+

+ запускает команду один раз для групп имен файлов (для повышения эффективности, а не один на один раз). Из-за того, как работает подстановка, он идентичен {} +, так как аргумент просто удален и заменен кучей имен файлов.

Как я могу исправить свой сценарий также для разнесенного имени файла?

Вы можете заставить его работать в 95% случаев, просто изменяя какие символы Баш использует для разделения, с помощью использования IFS переменной:

IFS=$'\n' 
for dir in $(find "$DIR" -type d) 
do 
    echo "Directory: >> $dir <<" 
done 

Это делает Баш разделение на только перевод строки, а чем по умолчанию все пробелы (это может иметь некоторые интересные побочные эффекты в остальной части вашего кода, поэтому вы можете захотеть впоследствии установить значение IFS на свое оригинальное название).

Имена файлов также могут содержать линейные каналы. Лучший подход заключается в использовании:

while IFS= read -d '' -r dir 
do 
    echo "Directory: >> $dir <<" 
done < <(find "$DIR" -type d -print0) 

, что делает find выходные файлы, разделенные NUL байт, что имена файлов не могут содержать.

+0

Ошибка, если имя каталога начинается с пробелов, а другая версия эха будет вести себя по-разному с разными настройками $ adir. Всегда используйте 'IFS = read -r', если у вас нет особых причин не знать и точно знать, что такое последствия. –

+0

Спасибо, что ответили на все мои подтексты! – optimusfrenk

Смежные вопросы