Сыр с ваапи

У Bash есть специальная переменная IFS.

используется bash, чтобы знать, как разбить строку на список файлов. (Внутренний разделитель полей)

По умолчанию он содержит пробел, табуляцию и новую строку.

for f in `find ... будет разделяться на символы, содержащиеся в переменной $ IFS. Если в именах файлов, возвращаемых командой find, есть новая строка или пробел, она будет рассматриваться как другое имя файла, и, таким образом, цикл будет выполняться для каждой части имени.

$ ls -l -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 my?bad.exe -rw-r--r-- 1 marko marko 0 2010-11-01 12:06 space bad.exe $ for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space) ITERATING (bad.exe) ITERATING (./my) ITERATING (bad.exe)

We может настроить переменную $ IFS, но это сложно. Давайте посмотрим, почему:

(Проверьте этот код в сценариях, чтобы изменение переменной IFS не осталось в вашей оболочке, вы можете запутаться)

$ IFS=""; for f in $(find -name "*.exe"); do echo "ITERATING ($f)"; done ITERATING (./space bad.exe ./my bad.exe)

Как вы можно увидеть, теперь у bash нет правила разбивать строку, возвращаемую командой find, и обрабатывает весь вывод как одно значение.

Ясно, что проблема заключается в том, что если мы используем for f in `find...., мы не можем отличить новую строку, содержащуюся в файле, от новой строки, сгенерированной командой find.

Теперь ради полноты я покажу вам, как сделать ваш подход работать, но, пожалуйста, см. более легкое решение в конце ответа.

Мы могли бы использовать другие символы разделителя и исправить вашу текущую проблему:

[ f3]

Здесь команда find -name "*.exe" -exec echo -n {}: \; возвращает список файлов, разделенных символом «:» (которые не являются законными в именах файлов Windows).

Теперь следующим шагом было бы фактически удалить эти файлы. Учитывайте, что последний файл заканчивается символом «:», и, таким образом, bash выполняет итерацию в последний раз с пустой строкой.

IFS=":"; for f in $(find -name "*.exe" -exec echo -n {}: \;); do if [ ! -z "$f" ]; then rm "$f"; fi; done;

Вы должны также выполнить свой тест basename / dirname в этом цикле , как вы это делали раньше.

Однако это решение является уродливым и работает только потому, что мы имеем символ, на который мы можем положиться.

Получается что команда find сама может выполнять команды для каждого найденного файла.

find -name "*.exe" -exec ./yourscript.sh {} \;

Затем yourscript.sh wil lget полное имя в $ 1, и вы можете удалить его с помощью rm "$1", даже если он содержит новые строки и пробелы .

Команда find также может использоваться для выполнения встроенного теста basename / dirname внутри вашего скрипта, но это более продвинутая тема.

1
задан 4 September 2012 в 15:59

1 ответ

У меня нет ответа, но, возможно, тестирование с помощью gstreamer-properties приведет вас куда-нибудь. Сыр просто использует gstreamer, поэтому, если вы можете заставить его работать в gstreamer-properties, тогда он будет работать в сыре.

0
ответ дан 26 May 2018 в 00:31

Другие вопросы по тегам:

Похожие вопросы: