Loop recursively with two variables for a specific extension with Bash
我正在尝试使用AtomicParsley将唱片集艺术添加到M4A文件中。以下内容适用于给定文件夹(有多个M4A文件,但只有一个cover.jpg):
1 | for f in *.m4a; do AtomicParsley"$f" --artwork cover.jpg --overWrite; done |
由于我想递归地执行此操作(每个文件夹有一个唯一的cover.jpg和多个m4a文件),并且所有子文件夹都具有相同的图像名称(即cover.jpg,尽管它们不同),所以我尝试了下面的操作,但它从第一个子文件夹中选择cover.jpg并应用于所有其他子文件夹(这是错误的,因为每个子文件夹都有自己的C超过JPG
1 2 3 4 5 | for f in **/*.m4a; do for j in **/cover.jpg; do AtomicParsley"$f" --artwork $j --overWrite done done |
更容易想到的是找到每个包含
1 2 3 4 5 6 7 8 | shopt -s globstar shopt -s nullglob for c in **/cover.jpg; do d=${c%/cover.jpg} for f in"$d"/*.m4a; do AtomicParsley"$f" --artwork"$c" --overWrite done done |
试试这个:
1 2 3 | for file in **/*.m4a; do AtomicParsley"$file" --artwork"$(dirname"$file")/cover.jpg" --overWrite done |
试试这个:
1 2 3 4 5 | main_dir="/path/to/dir" while IFS= read -r -d '' m4a_file do AtomicParsley"$m4a_file" --artwork"${m4a_file%/*}/cover.jpg" --overWrite done < <(find"$main_dir" -type f -name"*.m4a" -print0) |
这也是可能的:
1 2 3 4 5 6 7 8 | shopt -s globstar shopt -s nullglob main_dir="/path/to/dir" cd"$main_dir" for m4a_file in **/*.m4a do AtomicParsley"$m4a_file" --artwork"${m4a_file%/*}/cover.jpg" --overWrite done |
默认行为或全局化是,如果没有匹配项,则全局模式将扩展到自身。当在
对于更复杂的解决方案(有点过分杀伤力),允许您添加更多功能并使用相同的例程稍后执行不同的处理,您可以这样做:
1 2 3 4 5 6 7 8 9 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 | parsley_file() { AtomicParsley"$1" --artwork cover.jpg --overWrite } doforeach_arg() { local callback="$1" shift local arg for arg in"${@}"; do"${callback}""${arg}"; done } parsley_dir() ( # use '(',')' for subshell so shopt only affects this function local dir="${1}" shopt -s nullglob doforeach_arg parsley_file"${dir}"/*.m4a ) find_dirs() { find"${1}" -type d | sort } doforeach_line() { local callback="${1}" local line while read line; do"${callback}""${line}"; done } parsley_dirs() { find_dirs"${1}" | doforeach_line parsley_dir } parsley_dirs"." |
否则,如果您想这样做,那么对于几乎一个行程序来说就更简单了:
1 2 | shopt -s nullglob find"$PWD" - type d | while read dir ; do cd"$dir" && [[ -f cover.jpg ]] && ( for f in *.m4a ; do AtomicParsley"$f" -cover cover.jpg ; done ) ; done |