LINUX.ORG.RU

Скрипт на bash: с помощью parallel выполнить фукнцию для каждого файла

 ,


0

2

Есть скрипт:

#!/bin/bash
#find -type f -printf '%P\n' | parallel -j+0 ~/Скрипты/transcodev2.sh "{}" ~/Музыка.ogg
input="$1"
corr_name=$(echo "$input" | sed 's/[\?\*\:]/_/g')
output="$2/$corr_name"
mkdir -p "$(dirname "$output")"
if [[ $input == *.flac ]]
then
	avconv -i "$input" -c:a libvorbis -q:a 10 "${output%.flac}".ogg < /dev/null
else
	cp "$input" "$output"
fi
Суть проста: все flac в моей коллекции перегоняет в ogg, остальные файлы так и копирует, в итоге я получаю отдельную иерархию с перекодированными файлами, + имена адаптируются под FAT32. Запускаю так:
cd Музыка && find -type f -printf '%P\n' | parallel -j+0 ~/Скрипты/transcodev2.sh "{}" ~/Музыка.ogg
Но мне надоело фактически вручную выполнять часть работы. Мне хотелось бы, чтобы всё это выполнялось скриптом, которому просто передаются как аргументы путь к входной коллекции и путь к выходной коллекции. Я попробовал всё содержимое скрипта назначить функцией, сделать ей export, и вот эти команды с find запихнуть в скрипт после объявления функции, но, по видимому, parallel не видит эту функцию, хотя я её и экспортировал. Не могли бы вы помочь мне с этим разобраться? Хотелось бы уместиться в один скрипт. Заранее спасибо

★★

Так вот сработает?

from_dir=$(readlink -f $1)
to_dir=$(readlink -f $2)

mkdir -p $2

convert_flac_to_ogg () {
    new_path=$(echo "$1" | sed -r "s:$from_dir:$to_dir:")
    mkdir -p $(dirname "$new_path")
    avconv -i "$1" -c:a libvorbis -q:a 10 "${new_path%.flac}".ogg
}

export -f convert_flac_to_ogg
find $from_dir -name "*.flac" | parallel convert_flac_to_ogg
anonymous ()
Ответ на: комментарий от Norong

parallel на локальной системе запускает данную ему команду через /bin/sh -c 'команда', а в debian это наверняка ссылка на dash, который экспортированных переменных не понимает.

ABW ★★★★ ()
Ответ на: комментарий от ABW
convert_func () {
input="$1"
corr_name=$(echo "$input" | sed 's/[\?\*\:]/_/g')
output="$2/$corr_name"
mkdir -p "$(dirname "$output")"
if [[ $input == *.flac ]]
then
	avconv -i "$input" -c:a libvorbis -q:a 10 "${output%.flac}".ogg < /dev/null
else
	cp "$input" "$output"
fi
}
export -f convert_func
export SHELL=/bin/bash PARALLEL_SHELL=/bin/bash
find -type f -printf '%P\n' | parallel -j+0 convert_func "{}" ~/Музыка.ogg

Похоже, что работает. Большое спасибо!

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

Кстати, а такое экспортирование переменных не скажется на остальной системе?

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

Я сделал вот так:

env SHELL=/bin/bash PARALLEL_SHELL=/bin/bash parallel -j+0 convert_func «{}» ~/Музыка.ogg

Вроде бы, всё в порядке.

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

Итог таков:

#!/bin/bash
collection_in="$1"
collection_out="$2"

convert_func () {
input="$1"
corr_name=$(echo "$input" | sed 's/[\?\*\:]/_/g')
output="$2/$corr_name"
mkdir -p "$(dirname "$output")"
if [[ $input == *.flac ]]
then
	avconv -i "$input" -c:a libvorbis -q:a 10 "${output%.flac}".ogg < /dev/null
else
	cp "$input" "$output"
fi
}

export -f convert_func
export collection_in collection_out
find "$collection_in" -type f -printf '%P\n' | env SHELL=/bin/bash PARALLEL_SHELL=/bin/bash parallel -j+0 convert_func "$collection_in"/"{}" "$collection_out"
Работает вполне хорошо, но если у кого-нибудь найдётся критика и рекомендации - готов приехать выслушать.

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

А что будет, если указать в качестве collection_in и collection_out абсолютный путь? Или ты так не будешь делать?

Тоись по факту у тебя

output="$collection_out/$collection_in"

и скрипт придётся запускать только из папки $collection_in. Так что ли?

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

Было так, но я помедитировал ещё и получил:

#!/bin/bash
collection_in="$1"
collection_out="$2"

convert_func () {
	input="$1"
	corr_name=$(echo "${input/"$collection_in/"}" | sed 's/[\?\*\:]/_/g')
	output="$2/$corr_name"
	mkdir -p "$(dirname "$output")"
	if [[ $input == *.flac ]]
	then
		avconv -i "$input" -c:a libvorbis -q:a 10 "${output%.flac}".ogg < /dev/null
	else
		cp "$input" "$output"
	fi
}

export -f convert_func
export collection_in collection_out
find "$collection_in" -type f -printf '%P\n' | env SHELL=/bin/bash PARALLEL_SHELL=/bin/bash parallel -j+0 convert_func "$collection_in"/"{}" "$collection_out"
И отныне можно указать два аргумента (абсолютных или относительных, безразлично).

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