Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 对整个树中的所有文件执行某些操作_Bash_Unix - Fatal编程技术网

Bash 对整个树中的所有文件执行某些操作

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

场景是,我想将所有音乐文件从.mp3转换为.ogg。它们在一个名为“音乐”的文件夹中。此文件夹中有文件夹和文件。这些文件是.mp3。目录可能包含.mp3或进一步包含.mp3或目录的目录,等等。这是因为有些艺术家的专辑有部分,有些没有,等等

我想编写一个脚本,使用avconv转换每个文件。 基本上,我要做的是手动
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