将所有不同子文件夹中的.apa文件转换为.flac文件。

我试图使用命令行上的avconv将一些.ape文件转换为.flac文件;显然,这里的重点不是avconv;它的语法非常简单,avconv -i inputApeFile.ape outputFlacFile.flac
问题在于这些文件嵌套在更多的子文件夹中;也就是说,我有一个艺术家文件夹,然后是各种CD子文件夹,每个子文件夹中都包含不同的.ape文件。 我该如何将所有文件转换并保存到原始文件所在的同一文件夹中,但使用.flac扩展名?
如果可能的话,我希望只使用单行的shell命令,而不使用脚本。我认为应该是这样的:
avconv -i 'ls -R | grep ape' '???'

但是我卡在第二部分(也许可以使用sed?!?)
5个回答

你需要的命令是:
find /path/to/MainDir/ -type f -name "*.ape"  -execdir sh -c ' avconv -i "$1" "${1%.ape}.flac" ' _ {} \;

这将查找每个具有.ape后缀的文件,然后将其转换为相同的文件名,使用.flac后缀保存在原始文件所在的位置。 < p > {}是当前找到的文件的路径。
请参见此处的测试。


现在ffmpeg再次成为首选而不是avconv,并且有很多便宜的多核计算机(例如8核XU4只需60美元),我发现以下方法最有效:
#!/bin/bash

#
# ape2flac.sh
#

function f2m(){
        FILE=$(echo "$1" | perl -p -e 's/.ape$//g');
        if [ ! -f "$FILE".flac ] ; then
                ffmpeg -v quiet -i "$FILE.ape" "$FILE.flac"
        fi
}
export -f f2m
find "$FOLDER" -name '*.ape' | xargs -I {} -P $(nproc) bash -c 'f2m "$@"' _ "{}"

下面的(Python)脚本应该可以完成这个任务。将其复制到一个空文件中,保存为convert.py,在脚本的头部设置文件目录(convert_dir =),然后通过命令运行它:
python3 /path/to/convert.py

剧本

#!/usr/bin/env python3

convert_dir = "/path/to/folder/tobeconverted"

import os
import subprocess

for root, dirs, files in os.walk(convert_dir):
    for name in files:
        if name.endswith(".ape"):
            # filepath+name
            file = root+"/"+name
            # to use in other (convert) commands: replace the "avconv -i" by your command, and;
            # replace (".ape", ".flac") by the input / output extensions of your conversion
            command = "avconv -i"+" "+file+" "+file.replace(".ape", ".flac")
            subprocess.Popen(["/bin/bash", "-c", command])
        else:
            pass

感谢您的回复和时间,Jacob。不过,如果可能的话,我希望只使用一行命令而不使用脚本(对此我先前没有说明,抱歉)。 - tigerjack
1@tigerjack89 嗯,也许其他人在类似的情况下可以使用它;语法<command> <inputfile> <outputfile>非常常见。 - Jacob Vlijm

这是user1133275的答案的简化版本,它按顺序运行(因此速度较慢),不使用perl,而是使用xargs -0来处理包含空格、引号、括号、方括号、管道和其他特殊字符的文件名,否则如果以原始形式处理,脚本将失败。
find . -iname '*.ape' -print0 | xargs -0 -I {} ffmpeg -i '{}' '{}.flac'

⚠️ 上述解决方案 ⬆️ 的缺点是原始文件名中的 .ape 扩展名未被移除,新文件将具有 .ape.flac 扩展名。
为了替换现有的扩展名,可以使用 bash 正则表达式,因此以下命令将创建具有正确的 .flac 扩展名的文件:
find . -iname '*.ape' -print0 | xargs -0 -I{} bash -c 'ffmpeg -i "${1}" "${1%.*}.flac"' -- {}

您正在寻找的单行命令是:
find -type f -name "*.ape" -print0 | xargs -0 avconv -i
find 命令将提供仅以 .ape 结尾的文件。
find 命令将为 avconv 命令提供相对路径,以便它可以转换这些文件并将它们保存在与输入文件(即 .ape)相同的文件夹中。
find 命令将查找该目录中的所有文件,无论它们被保存在子目录中多深。


2这样行不通;avconv不能像那样从标准输入中接受输入文件。 - evilsoup
1输出文件夹怎么样? - tigerjack
@evilsoup 我已经更新了答案,xargs可以解决这个问题。请尝试一下。 - Alex Jones