LINUX.ORG.RU

bash loop in all ./subdirectories/*/*

 ,


0

4

Пытаюсь все mp3 файлы во всех сабдиректориях (рекурсивно) переконвертировать, но вот следующий код охватывает только несколько уровней этих сабдиректорий, мне надо все:

#/bin/bash

for i in **/*.mp3;
  do name=`echo $i | cut -d'.' -f1`;
  ffmpeg -i "$i" -vn -acodec aac -b:a 128k -y "converted/$name.aac"
  echo "converted/$name";
done

ЧЯДНТ?

Deleted
#!/bin/sh

IFS=$'\n' for i in $(find . -type f -iname "*.mp3"); do
  name="${i##*/}"
  name="${name%%.mp3}"
  ffmpeg -i "$i" -vn -acodec aac -b:a 128k -y "converted/${name}.aac" && \
    printf 'converted/%s\n' "${name}"
done
r3lgar ★★★★★
()
Ответ на: комментарий от r3lgar

./vert: line 3: syntax error near unexpected token `do'
./vert: line 3: `IFS=$'\n' for i in $(find . -type f -iname "*.mp3"); do'
[\code]
Deleted
()
Ответ на: комментарий от r3lgar
#!/bin/sh

IFS=$'\n' 
for i in $(find . -type f -iname "*.mp3"); do
  name="${i##*/}"
  name="${name%%.mp3}"
  ffmpeg -i "$i" -vn -acodec aac -b:a 128k -y "converted/${name}.aac" && \
    printf 'converted/%s\n' "${name}"
done

А вот так работает, спасибо!

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

А вот так работает

Да, накосячил я малость.

спасибо!

Лучше отметь тему решённой.

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

xargs распараллеливает, но GNU parallel делает это лучше

find -iname '*.mp3' -print0 |
  xargs -P `nproc` -0I{} sh -c "
    mkdir -p \"converted/\$(dirname '{}')\";
    ffmpeg -i '{}' -vn -acodec aac -b:a 128k -y \"converted/\$(dirname '{}')/\$(basename '{}' .mp3).aac\"
  "

для parallel ща напишу

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

Вот parallel

find -iname '*.mp3' -print0 |
parallel -0 "
  mkdir -p converted/{//};
  ffmpeg -i {} -vn -acodec aac -b:a 128k -y converted/{.}.aac"

гораздо проще, чем for и xargs, искаропки использование всех процессоров, а с настройкой и использование всех компов, куда есть ssh.

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

Минусов у parallel два, оба вытекают из того, что автор - учёный:

1) оно просит не забыть ссылку в научной работе (отключается)

2) страница мана длиной от Земли до Луны

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

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

Deleted
()
Ответ на: комментарий от legolegs

parallel на локалхосте — из пушки по воробьям, ящитаю. А вот для выполнения одной команды на куче удалённых машин он сильно упрощает жизнь.

r3lgar ★★★★★
()

ЧЯДНТ?

Надо вам изучить понятие рекурсии.

scan() {
        local p
        for p in "$1/"* ; do
                [[ -L "$p" ]] && continue
                if [[ -d "$p" ]]; then
                        scan "$p"
                elif [[ "${p:0-4:4}" == .mp3 && -f "$p" ]]; then
                        convert "$p"
                fi
        done
}
scan "${1:-.}"
vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от legolegs

Вот parallel гораздо проще, чем for и xargs искаропки

Нету parallel из коробки. И для обработчика по одному файлу вызывать миллион раз bash и еще, между прочим, каждый раз он будет синтаксически жевать один и тот же текст, в отличии от цикла на bash, где синтаксический разбор будет ровно один раз. Паралельность и на bash легко реализуется:

PARALLEL=4
jobs_is_parallel_available() {
        local -i i
        local l
        while true; do
                i=0
                while read l; do
                        i+=1
                done < <(jobs -r)
                [[ $i -lt $PARALLEL ]] && break
                sleep 0.1s
        done
}

while read l; do
   ### ASYNC
   convert_file "$l" &
   jobs_is_parallel_available
done < <(find / -type f -iname '*.flac')
wait

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

Job control в скриптах разве не надо ручками включать?

Вы путаете с fg/bg — это действительно завязано с tty.

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

Мне показалось, что пройтись по всем сабдиректориям - задача базовая, а значит и решение должно бы лежать где-то на поверхности (например путем изменения **/*.mp3 на что-то почти столько же простое) и я его не вижу.

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

Мне показалось, что пройтись по всем сабдиректориям - задача базовая,

Вам показалось. Вот скажем, ls не умеет *.mp3. А find - не сортирует. Потому надо взять нужное и сделать конкретную задачу.

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

Мне показалось, что пройтись по всем сабдиректориям — задача базовая

И вы правы.

а значит и решение должно бы лежать где-то на поверхности (например путем изменения **/*.mp3 на что-то почти столько же простое) и я его не вижу.

И вы даже верно запомнили синтаксис — две звездочки, просто забыли включить поддержку этих звездочек. :-)

shopt -s globstar

А еще не стоит пренебрегать nullglob’ом или failglob’ом (по вкусу, я бы взял первое):

shopt -s nullglob globstar

Зело пекутся об обратной совместимости...

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

for i in $(find . -type f -iname «*.mp3»); do
А вот так работает, спасибо!

Вы ошибаетесь, *это* как раз не работает. Так же, как и любой другой for ... in $(...).

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

shopt -s nullglob globstar

благодарю за замечание, моя картина мира восстановлена, хе-хе

Вы ошибаетесь, *это* как раз не работает. Так же, как и любой другой for ... in $(...).

я как понимаю это можно решить через -print0?

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

shopt -s nullglob globstar


благодарю за замечание, моя картина мира восстановлена, хе-хе

Всегда пожалуйста.

Вы ошибаетесь, *это* как раз не работает. Так же, как и любой другой for ...
in $(...).


я как понимаю это можно решить через -print0?

Да нет. Нулевой символ — это про концы строк (которые обычно десятый, \n), а тут идет ломка строки по всем пробелам.

Чтение потока ничем не отличается от чтения файла, и делается точно так же:

while read -r; do
    ... "$REPLY" ...
done < \
     <(...)

Впрочем, вот теперь, для пущей уверенности, можно и строки делить по нулевому символу:

while read -rd ''; do
    ... "$REPLY" ...
done < \
     <(... -print0)
Zmicier ★★★★★
()
Ответ на: комментарий от Deleted

Да всегда пожалуйста, только лучше бы было, наверное, какую-нибудь методичку почитать? ;-)

Если прилагаемая к Башу документация уже просмотрена, то все те материалы под ред. Грега Вулиджа, например...

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

teod0r всмысле для чего нужен -print0 или -d ''?

ну я прочел man find

-print0
True; print the full file name on the standard output, followed by a null character (instead of the newline character that -print uses). This allows file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output. This option corresponds to the -0 option of xargs.

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

А -d '' для чего нужен уже объяснил Zmicier.

Если прилагаемая к Башу документация уже просмотрена, то все те материалы под ред. Грега Вулиджа, например...

да в доки я почти и не смотрел, а книжечку почитаю как нибудь : )

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.