LINUX.ORG.RU

Обработка имен файлов с пробелами, полученных от команды find - оно работает, но странно глючит

 , , , ,


0

2

Наконец-то я почти нашел относительно адекватное решение старого вопроса: как в цикле правильно перебрать имена файлов, полученных от команды find, причем в именах файлов могут встречаться пробелы?

Решение такое:

find -name \*.mp3 -or -name \*.MP3 -or -name \*.Mp3 -or -name \*.ogg -print0 | while IFS= read -r -d '' file; 
do

    echo "Processing ${file}"
 
done

Однако есть проблема. Если в заданном каталоге вручную в консоли вызвать одну команду find, то она, как и положено, найдет все мои ~300 файлов:
find -name \*.mp3 -or -name \*.MP3 -or -name \*.Mp3 -or -name \*.ogg
./Last love jam.mp3
./WindJam/Minus 4.mp3
./WindJam/Minus 3.mp3
./WindJam/Minus 2.mp3
./WindJam/Minus 1.mp3
./Thrash-electronics JAM.mp3
... 300 файлов ...

Если же в этом же каталоге запустить полный вышеуказанный скрипт, то он найдет только *.ogg файлы.

Почему так? Что в скрипте еще надо исправить, что бы обрабатывались все файлы?

★★★★★

Ответ на: комментарий от urxvt

И что? Согласно документации он заменяет символы конца строки на 0x00. Как это связано с тем, что видны только *.ogg файлы? Причем эти *.ogg файлы находятся в разных директориях.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Ага, нашел в чем была проблема.

Оказывается, -print0 применяется только к минимальной части составного условия, а не ко всей команде find. Что весьма неожиданно. Как применить ко всей команде - так и не понял.

Но зато зная эту особенность, можно написать правильно работающий скрипт:

#!/bin/bash

find -name \*.mp3 -print0 \
     -or -name \*.MP3 -print0 \
     -or -name \*.Mp3 -print0 \
     -or -name \*.ogg -print0 \
     | while IFS= read -r -d '' file; 
do

    echo "Processing ${file}"
 
done

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от Xintrea

Ну так ты же задал пустой разделитель -d ". Убери его и -print0 и должно все работать. IFS тоже не нужон.

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

Ты сам то проверил? Как без -print0 будут правильно обрабатываться пробелы в именах файлах?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Как применить ко всей команде - так и не понял.

Я так понимаю, можно задействовать скобки.

     find / \( -newer ttt -or -user wnj \) -print
             Print out a list of all the files that are either owned by “wnj”
             or that are newer than ttt.

urxvt ★★★★★
()
Последнее исправление: urxvt (всего исправлений: 1)
Ответ на: комментарий от urxvt

Ты не фантазируй, а проверяй сначала свои предположения. Потому что с твоими правками имеем:

find -name \*.mp3 \
     -or -name \*.MP3 \
     -or -name \*.Mp3 \
     -or -name \*.ogg \
     | while read -r '' file;
do

    echo "Processing ${file}"

done

./soundConvert02.sh: строка 7: read: «»: это недопустимый идентификатор

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от Xintrea

Да, проверял.

$ ls -1 *.mp3 *.ogg
bar.ogg
foo bar.mp3
foo.mp3
$ cat test.sh 
find . -name \*.mp3 -or -name \*.MP3 -or -name \*.Mp3 -or -name \*.ogg | while read file;
do

    echo "Processing ${file}"

done
$ bash test.sh 
Processing ./bar.ogg
Processing ./foo.mp3
Processing ./foo bar.mp3
$ 


Как без -print0 будут правильно обрабатываться пробелы в именах файлах?

Так read читает до \n а не пробела.

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

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

Xintrea ★★★★★
() автор топика
#!/bin/bash

# v1
find -type f -iname "*.ogg" -or -iname "*.mp3" -print0 | xargs -r0I{} bash -c '
 echo "Processing {}";
 ls -la "{}";
 ./my_script.sh "{}"
'

#v2
readarray -t ARR < <(find -type f -iname "*.ogg" -or -iname "*.mp3")

for f in "${ARR[@]}"; do
 echo "Processing ${f}"
done

DiMoN ★★★
()
Последнее исправление: DiMoN (всего исправлений: 2)
find . -regextype egrep -iregex ".+(mp3|ogg)" -printf "Processing %p\n"
dmitry237 ★★★★
()

-iname, чтобы не учитывать регистр букв.

ox55ff ★★★★★
()
Ответ на: комментарий от Xintrea

Оказывается, -print0 применяется только к минимальной части составного условия, а не ко всей команде find.

вот это поворот.
* побежал чинить свои скрипты.

teod0r ★★★★★
()
Ответ на: комментарий от urxvt

Одно дело когда ошибки получились случайно и их фиксят при обнаружении, а другое - когда про них изначально знают и так и оставляют. Второе это однозначно плохо.

firkax ★★★★★
()
Ответ на: комментарий от vtVitus

Да. Но в таком виде оно уже менее читабильно, чем было. Ну то есть, скобки-то можно оставить, но перечислить три корректных капитализации, имхо, нагляднее и проще, чем сказать, что регистр неважен, а потом запретить один из вариантов, да ещё и с двумя дополнительными скобками необходимыми.

CrX ★★★★★
()
Ответ на: комментарий от firkax

В согласен. Но! Написать абсолютно корректную программу очень сложно и часто нецелесообразно (нерентабельно). Потому, никто не обрабатывает в домашних однострочниках все теоретически возможные варианты. Споры и усложнение в теме про -print0 сам можешь видеть — -print0 все усложняет на пустом месте.

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

-print0 все усложняет на пустом месте.

наоборот упрощает, когда есть чехарда с пробелами и метасимволами.

я же показал, как надо исп. read для нуль-строк

Обработка имен файлов с пробелами, полученных от команды find - оно работает, но странно глючит (комментарий)

futurama ★★★★★
()
Ответ на: комментарий от teod0r

Пустой -d это тоже NUL

-d delim
                     The first character of delim is used to terminate the input  line,
                     rather than newline.  If delim is the empty string, read will ter‐
                     minate a line when it reads a NUL character.
futurama ★★★★★
()
Ответ на: комментарий от legolegs

find ... -exec, остальное ненужно.

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

Xintrea ★★★★★
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.