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

时间:2015-11-19 07:35:01

标签: bash unix

场景是我想将我的所有音乐文件从.mp3转换为.ogg。它们位于名为" Music"的文件夹中。在此文件夹中有文件夹和文件。文件是.mp3s。目录可能包含.mp3s或目录,其中还包含.mp3s或目录,依此类推。这是因为有些艺术家的专辑有部分,有些没有,等等。

我想编写一个使用avconv转换每个文件的脚本。 基本上,我要做的是手动cd到每个目录并运行以下内容:

for file in $(ls); do avconv -i $file `echo \`basename $file .mp3\`.ogg`; done

这成功地让我得到了我想要的东西。但是,这并不是很好,因为我有很多文件夹,并且手动进入每个文件夹并执行此操作很慢。

我的问题是,如何在任何具有.mp3s的目录中编写运行此脚本的脚本,然后进入它找到的任何子目录并递归调用自身?我的直觉告诉我使用Perl或Python,因为它的复杂性。

感谢您的任何建议!

4 个答案:

答案 0 :(得分:0)

我不熟悉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")

注意:这不会移除原始.mp3,并且space之间的< <是必需的。另请注意,for file in $(ls)充满了潜在的错误。

答案 1 :(得分:0)

你可以用一个班轮中的bash来做到这一点:

首先,您找到与下一个模式匹配的所有文件(类型为file(-type f))&#34; * .mp3&#34;。阅读你使用的每一个&#39;而#39;并调用avconf。 对于交换扩展,我更喜欢&#39; sed&#39;命令,保留文件夹,这样你就不需要&#39; cd&#39;命令。 请注意,您必须在$ FN变量上加上引号,因为它可以包含空格。

find -type f -iname "*.mp3" | while read "FN" ; do avconf -i "$FN" $(echo "$FN" | sed 's/\.mp3/\.ogg/g') ; done

答案 2 :(得分:0)

find <music-folder> -type f -name '*.mp3' | \
    xargs -I{} bash -c 'mp3="$0"; ogg="${mp3%.mp3}.ogg"; avconv -i "$mp3" "$ogg";' {}

在“奇怪”的文件名中包含空格,引号和其他奇怪符号的情况下,这应该存在。

答案 3 :(得分:0)

您可以列出具有绝对路径的目录,并使用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