9

I was trying to convert some .ape files to .flac files using avconv on command line; obviously, avconv is not the main point here; its syntax is pretty straightforward, avconv -i inputApeFile.ape outputFlacFile.flac.

The point is that the files are nested in more subfolders; i.e., I have the Artist folder, then various CD subfolders, each of one contain different .ape files. How can I convert all the files and then save them in the same folder of the original file but with the .flac extension?

If it is possible, I'd like to use only shell command on a single line without using scripts. I think it should be something like that

avconv -i 'ls -R | grep ape' '???'

but I'm stuck with the second part (maybe using sed??!?)

αғsнιη
  • 36,350
tigerjack
  • 2,635

5 Answers5

13

The command that you need is:

find /path/to/MainDir/ -type f -name "*.ape"  -execdir sh -c ' avconv -i "$1" "${1%.ape}.flac" ' _ {} \;

This will find each file that has .ape suffix and then convert it with the same filename with .flac suffix to the same location as original file is located.

{} is the path of current found file.
See the test from here

αғsнιη
  • 36,350
1

Now that ffmpeg is preferred over avconv again, and there are cheap many core computers ($60 for an 8 core XU4) I fount the following to be most effective;

#!/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 "$@"' _ "{}"
1

The (python) script below should do the job. Copy it into an empty file, save it as convert.py, set the directory to the files in the head section of the script (convert_dir =) and run it by the command:

python3 /path/to/convert.py

The script

#!/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 Vlijm
  • 85,475
0

Simplified version of user1133275's answer which runs sequentially (and therefore is slower), and which does not use perl but does use xargs -0 in order to deal with file names containing spaces, quotes, parens, brackets, pipes and other special characters that would otherwise make the script fail if treated in raw form:

find . -iname '*.ape' -print0 | xargs -0 -I {} ffmpeg -i '{}' '{}.flac'

⚠️ The solution above ⬆️ has the downside that the original .ape extension is not removed from the file name and the new files will have the .ape.flac extension.

In order to replace the existing extension a bash regex can be used, so the following command will create files with correct .flac extensions:

find . -iname '*.ape' -print0 | xargs -0 -I{} bash -c 'ffmpeg -i "${1}" "${1%.*}.flac"' -- {}
ccpizza
  • 1,564
  • 19
  • 20
-1

one line command you were looking for:
find -type f -name "*.ape" -print0 | xargs -0 avconv -i
find command will provide only files ending with .ape
the find command will give the relative path to avconv command so that it can convert those files and keep them in same folder as the input file (i.e. .ape).
find command will find all the files in that directory irrespective of how deep they are kept in subdirectory

Alex Jones
  • 8,192