Minęło trochę czasu, odkąd używałem make
, więc wytrzymaj ze mną ...
Mam katalog flac
zawierający pliki .FLAC. Mam odpowiedni katalog mp3
zawierający pliki MP3. Jeśli plik FLAC jest nowszy niż odpowiadający mu plik MP3 (lub odpowiadający mu plik MP3 nie istnieje), chcę uruchomić kilka poleceń, aby przekonwertować plik FLAC na plik MP3 i skopiować tagi w poprzek.
Kicker: Muszę przeszukać flac
katalog rekurencyjnie i utworzyć odpowiednie podkatalogi w mp3
katalogu. Katalogi i pliki mogą mieć spacje w nazwach i są nazywane w UTF-8.
I chcę to wykorzystać make
do prowadzenia tego.
make
jest bliższe realizacji niż gołebash
.sh
skrypt, który przechodzi przez listę plików flac (find | while read flacname
), tworzymp3name
z tego a, uruchamia "mkdir -p" nadirname "$mp3name"
, a następnieif [ "$flacfile" -nt "$mp3file"]
konwertuje"$flacname"
na"$mp3name"
nie jest naprawdę magiczny. Jedyną cechą, którą faktycznie tracisz w porównaniu zmake
rozwiązaniem opartym na bazie, jest możliwośćN
równoległego uruchamiania procesów konwersji plikówmake -jN
.make
i posiadanie spacji w nazwach plików to sprzeczne wymagania. Użyj narzędzia odpowiedniego dla problematycznej domeny.Odpowiedzi:
Spróbowałbym czegoś podobnego
Kilka krótkich uwag dla
make
początkujących:@
na początku poleceń zapobiega ichmake
wydrukowaniu przed jego faktycznym uruchomieniem.$(@D)
jest częścią katalogu nazwy pliku docelowego ($@
)Nawet jeśli powinno to obsłużyć wszystkie znaki UTF-8 i inne rzeczy, zakończy się niepowodzeniem w przypadku spacji w nazwach plików lub katalogów, ponieważ
make
używa spacji do oddzielenia rzeczy w plikach makefile i nie jestem świadomy sposobu obejścia tego. Zostaje więc tylko skrypt powłoki, obawiam się: - /źródło
vpath
. Muszę przestudiować ten jeden z tych dni.find
uzyskać nazwy rekurencyjnie ...make -jN
. DoN
wykorzystania liczby konwersji, któremake
powinny przebiegać równolegle. Uwaga: Uruchomieniemake -j
bezN
uruchomi wszystkie procesy konwersji jednocześnie, co może być równoważne z bombą widelcową..PHONY: all
Linia mówi make, że przepis naall
cel ma zostać wykonany, nawet jeśli istnieje plik o nazwieall
nowszy niż wszystkie$(MP3_FILES)
.Możesz zdefiniować własną rekurencyjną funkcję wieloznaczną w następujący sposób:
Pierwszy parametr (
$1
) to lista katalogów, a drugi ($2
) to lista wzorców, które chcesz dopasować.Przykłady:
Aby znaleźć wszystkie pliki C w bieżącym katalogu:
Aby znaleźć wszystkie pliki
.c
i.h
wsrc
:Ta funkcja jest oparta na implementacji z tego artykułu , z kilkoma ulepszeniami.
źródło
make
jest Turing Tar Pit (patrz tutaj: yosefk.com/blog/fun-at-the-turing-tar-pit.html ). Nie jest to nawet takie trudne, ale trzeba przeczytać to: gnu.org/software/make/manual/html_node/Call-Function.html, a następnie „zrozumieć powtarzalność”. TY musieliście to napisać rekurencyjnie, dosłownie; nie jest to codzienne rozumienie „automatycznie dołączaj rzeczy z podkatalogów”. To rzeczywisty nawrót. Ale pamiętaj - „Aby zrozumieć nawrót, musisz zrozumieć nawrót”.FWIW, użyłem czegoś takiego w pliku Makefile :
Powyższy przykład wyszuka w bieżącym katalogu ( „.” ) Wszystkie „zwykłe pliki” ( „-type f” ) i ustawi
RECURSIVE_MANIFEST
zmienną make na każdy znaleziony plik. Następnie możesz użyć podstawień wzorców, aby zredukować tę listę, lub alternatywnie, podać więcej argumentów, aby znaleźć, aby zawęzić to, co zwraca. Zobacz stronę podręcznika, aby znaleźć .źródło
Moje rozwiązanie jest oparte na powyższym, używa
sed
zamiastpatsubst
modyfikować wyjściefind
AND ucieczki ze spacji.Przejście z flac / do ogg /
Ostrzeżenia:
źródło
Oto skrypt w Pythonie, który szybko zhakowałem, aby rozwiązać pierwotny problem: zachowaj skompresowaną kopię biblioteki muzycznej. Skrypt skonwertuje pliki .m4a (zakłada się, że jest to ALAC) do formatu AAC, chyba że plik AAC już istnieje i jest nowszy niż plik ALAC. Pliki MP3 w bibliotece zostaną połączone, ponieważ są już skompresowane.
Uważaj tylko, że przerwanie skryptu ( ctrl-c) spowoduje pozostawienie w połowie przekonwertowanego pliku.
Początkowo chciałem również napisać Makefile, aby to obsłużyć, ale ponieważ nie może on obsługiwać spacji w nazwach plików (zobacz akceptowaną odpowiedź) i ponieważ napisanie skryptu bash gwarantuje, że wprowadzi mnie w świat bólu, jest nim Python. Jest dość prosty i krótki, a zatem powinien być łatwy do dostosowania do twoich potrzeb.
Oczywiście można to ulepszyć, aby wykonywać kodowanie równolegle. Czytelnikowi pozostawiam to jako ćwiczenie ;-)
źródło
Jeśli używasz Bash 4.x, możesz użyć nowej opcji globowania , na przykład:
Ten rodzaj rekursywnego symbolu wieloznacznego może znaleźć wszystkie interesujące Cię pliki ( .flac , .mp3 lub cokolwiek innego). O
źródło
**
nie zadziała, ponieważ rozszerzony globbing to rzecz bash / zsh.