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