使用Bash以特定扩展的两个变量递归循环

时间:2017-02-12 01:25:06

标签: bash loops for-loop

我正在尝试使用AtomicParsley将专辑封面添加到m4a文件中。以下适用于给定的文件夹(有多个m4a文件但只有一个cover.jpg):

for f in *.m4a; do AtomicParsley "$f" --artwork cover.jpg --overWrite; done

因为我想以递归方式执行此操作(每个文件夹都有一个独特的cover.jpg和多个m4a文件)并且所有子文件夹都具有相同的图像名称(即,尽管它们不同,但是我们正在尝试使用cover.jpg)但它从第一个子文件夹中选择了cover.jpg并应用于所有其他子文件夹(这是错误的,因为每个子文件夹都有自己的cover.jpg)

for f in **/*.m4a; do
  for j in **/cover.jpg; do
    AtomicParsley "$f" --artwork $j --overWrite
  done
done

4 个答案:

答案 0 :(得分:3)

将此视为查找包含cover.jpg的每个目录更容易,然后查找该目录中的所有视频文件。

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)

试试这个:

for file in **/*.m4a; do
    AtomicParsley "$file" --artwork "$(dirname "$file")/cover.jpg" --overWrite
done

答案 2 :(得分:1)

试试这个:

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)

这也是可能的:

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

globstar shell选项以递归方式启用**通配(即进入子目录,子目录的子目录等)。

默认行为或通配是如果没有匹配,则glob模式会扩展为自身。当在for循环中发生这种情况时,您必须处理不存在的文件大小写,因为失败的glob将导致循环体在变量中使用无效的文件名执行一次。 nullglob选项更改了默认行为,以便失败的glob将扩展为空。在for循环的情况下,循环根本不会执行。

答案 3 :(得分:0)

对于一个更复杂的解决方案(过度杀伤)允许您添加更多功能并使用相同的例程,稍后进行不同的处理,您可以执行以下操作:

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

如果你想要的话,那么对于几乎单行的事情来说更简单:

<html>
<body>
    <table>
    <tbody data-bind="foreach: users">
        <tr>
            <td><span data-bind="text: firstName"></span></td>
            <td><input data-bind="value: firstName" type="text"></span></td>
            <td><span data-bind="text: lastName"></span></td>
            <td><input data-bind="value: lastName" type="text"></td>
        </tr>
    </tbody>
</table>
<script src="js/libs/knockout-3.2.0.js"></script>
<script>
function User(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

function UserListViewModel() {
    var self = this;

    self.users = ko.observableArray([
        new User("Joe", "Schmoe"),
        new User("James", "Ronald")
    ]);
}
ko.applyBindings(new UserListViewModel());
</script>
</body>
</html>