Bash 对整个树中的所有文件执行某些操作
场景是,我想将所有音乐文件从.mp3转换为.ogg。它们在一个名为“音乐”的文件夹中。此文件夹中有文件夹和文件。这些文件是.mp3。目录可能包含.mp3或进一步包含.mp3或目录的目录,等等。这是因为有些艺术家的专辑有部分,有些没有,等等 我想编写一个脚本,使用avconv转换每个文件。 基本上,我要做的是手动Bash 对整个树中的所有文件执行某些操作,bash,unix,Bash,Unix,场景是,我想将所有音乐文件从.mp3转换为.ogg。它们在一个名为“音乐”的文件夹中。此文件夹中有文件夹和文件。这些文件是.mp3。目录可能包含.mp3或进一步包含.mp3或目录的目录,等等。这是因为有些艺术家的专辑有部分,有些没有,等等 我想编写一个脚本,使用avconv转换每个文件。 基本上,我要做的是手动cd进入每个目录并运行以下操作: for file in $(ls); do avconv -i $file `echo \`basename $file .mp3\`.ogg`; don
cd
进入每个目录并运行以下操作:
for file in $(ls); do avconv -i $file `echo \`basename $file .mp3\`.ogg`; done
这成功地满足了我的需求。然而,这不是很好,因为我有很多文件夹,手动进入每个文件夹,执行起来很慢
那么,我的问题是,如何编写一个脚本,在任何有.mp3s的目录中运行它,然后进入它找到的任何子目录并递归地调用它自己?我的直觉告诉我使用Perl或Python,因为它的复杂性
谢谢你的建议 我不熟悉
avconv
,但假设您的命令是:
avconv -i inputname outputname
如果要将所有inputname.mp3
转换为inputname.ogg
的原始目录下的Music
,则在bash中应该可以执行以下操作:
#!/bin/bash
while read -r fname; do
avconv -i "$fname" "${fname%.mp3}.ogg"
done < <(find /path/to/Music -type f -name "*.mp3")
#/bin/bash
而read-r fname;做
avconv-i“$fname”“${fname%.mp3}.ogg”
完成<您可以用bash在一行程序中完成:
首先找到与下一个模式“*.mp3”匹配的所有文件(文件类型(-f类型))。阅读您使用“while”并调用avconf的每一项。
对于exchange扩展,我更喜欢使用“sed”命令,它保留文件夹,因此您不需要使用“cd”命令。
请注意,必须在$FN变量上加引号,因为它可以包含空格
find -type f -iname "*.mp3" | while read "FN" ; do avconf -i "$FN" $(echo "$FN" | sed 's/\.mp3/\.ogg/g') ; done
find-type f-name'*.mp3'|\
xargs-I{}bash-c'mp3=“$0”;ogg=“${mp3%.mp3}.ogg”;avconv-i“$mp3”“$ogg””{}
如果文件名中有空格、引号和其他奇怪的符号,则这种情况应该存在。您可以列出具有绝对路径的目录,并使用find$PWD-type d
语法递归地将cd放入每个目录:
仅在音乐目录中运行:
for d in $(find $PWD -type d)
do
cd $d
for file in $(find . -maxdepth 1 -type f)
do
echo $file
avconv -i $file `echo \`basename $file .mp3\`.ogg`
done
done
您真的希望使用递归吗?这不是一个简单的查找-名称'*.mp3'-exec sh-c'mp3=“{}”;ogg=“${mp3%.mp3}.ogg”;avconv-i“$mp3”“$ogg”\代码>足够?或shopt-s globstar;对于$rootdir/***.mp3中的mp3_文件;做任何事;完成
@4ae1e1我可能必须更新我的bash。3.2.54(1)-版本不支持glob_star
(至少在前面提到的格式中是这样)。@user3159253它是4.0中的新版本。请参阅。@4ae1e1这工作正常。是因为*/.mp3在任何目录中都只与所有匹配的文件相匹配吗?这是一个惊人的功能。如果有文件music.mp3.mp3
(输出文件将是music.ogg.ogg
)。改为使用参数展开。
for d in $(find $PWD -type d)
do
cd $d
for file in $(find . -maxdepth 1 -type f)
do
echo $file
avconv -i $file `echo \`basename $file .mp3\`.ogg`
done
done