- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
#!/usr/bin/env escript
-mode(compile).
main(["-p"|Filenames]) ->
put(pretend, true),
main(Filenames);
main(Filenames) ->
case get(pretend) of
true -> ok;
_ -> put(pretend, false)
end,
Albums = lists:filtermap(fun parse_name/1, Filenames),
lists:foreach(fun process_album/1, Albums).
process_album({Zip, Artist, Album}) ->
Dir = filename:absname(filename:join(Artist, Album)),
case filelib:wildcard(Dir ++ "/cover.*") of
[] ->
io:format("Will create ~p~n", [Dir]),
get(pretend) orelse do_process_album(Dir, Zip, Album);
_ ->
io:format("Ignoring ~p : ~p~n", [Artist, Album])
end.
do_process_album(Dir, Zip, Album) ->
ok = filelib:ensure_dir(Dir ++ "/fake"),
0 = exec(Dir, "/usr/bin/unzip", [Zip, "-d", Dir]),
postprocess(Album, Dir).
postprocess(Album, Dir) ->
Files = filelib:wildcard(Dir ++ "/*-*[0-9]*.flac"),
lists:foreach(fun(I) -> rename_flac(Album, I) end, Files).
rename_flac(Album, OldFile) ->
Dir = filename:dirname(OldFile),
OldName = filename:basename(OldFile),
Options = [{capture, all_but_first, list}],
{ok, RE} = re:compile(Album ++ " - ([0-9]+.*\\.flac)", [unicode]),
case re:run(OldName, RE, Options) of
{match, [NewName]} ->
io:format("New name: ~p~n", [NewName]),
NewFile = filename:join(Dir, NewName),
ok = file:rename(OldFile, NewFile);
nomatch ->
ok
end.
parse_name(Filename) ->
Opts = [{capture, ['band', album], list}],
case re:run(filename:basename(Filename), "(?<band>[^-]+) - (?<album>.*)\\.zip", Opts) of
{match, [Band, Album]} ->
{true, {filename:absname(Filename), Band, Album}};
nomatch ->
false
end.
-spec exec(file:filename(), file:filename(), [string() | binary()]) -> integer().
exec(Dir, CMD, Args) ->
Port = open_port( {spawn_executable, CMD}
, [ exit_status
, binary
, stderr_to_stdout
, {args, Args}
, {cd, Dir}
, {line, 300}
]
),
collect_port_output(Port, filename:basename(CMD)).
-spec collect_port_output(port(), string()) -> integer().
collect_port_output(Port, CMD) ->
receive
{Port, {data, {_, Data}}} ->
io:format("~s: ~s~n", [CMD, Data]),
collect_port_output(Port, CMD);
{Port, {exit_status, ExitStatus}} ->
ExitStatus
end.