J'essaie de faire passer par FFmpeg tous les fichiers et sous-dossiers sous le chemin d'accès dans lequel je lance la commande, afin de convertir tout fichier MKV en conteneur MP4.
La commande ci-dessous fonctionne, mais le nouveau fichier MP4 créé a toujours l'extension MKV en plus de la nouvelle extension MP4.
find ./ -iname '*.avi' -o -iname '*.mkv' -exec bash -c 'ffmpeg -i "{}" -vcodec copy -acodec copy "{}".mp4' \;
Par exemple :
abcd.mkv (original file)
abcd.mkv.mp4 (new file)
Comment ajuster la commande pour se débarrasser de l'extension de fichier d'origine?
Il existe un moyen plus simple de le faire, en plaçant votre commande ffmpeg
dans un script bash
et en utilisant bash
tools. Au lieu de:
find ./ -iname '*.avi' -o -iname '*.mkv' -exec \
bash -c 'ffmpeg -i "{}" -vcodec copy -acodec copy "{}".mp4' \;
Utilisez find
et xargs
pour transmettre une liste des noms de fichiers (y compris les noms de fichiers avec des espaces) à, par exemple, $HOME/bin/fixthem
(lecture man find;man xargs
):
find . -type f -iname '*.avi' -o -iname '*.mkv' -print0 |\
xargs -0 -r $HOME/bin/fixthem
Avec $HOME/bin/fixthem
étant quelque chose comme (et chmod +x
'd):
Remarque: non testé, mais exécuté par /usr/bin/shellcheck
.
#!/bin/bash
# convert the *.mkv and *.avi files to .mp4
# determine my name
me=$0
me=${me##*/}
# -h or --help
help () {
cat >&2 <<EOF
${me} [-h|--help] [-d|--debug] [-v|--verbose] [-n|--noaction] file file ...
${me}: -h or --help This message
${me}: -d or --debug List the commands we execute, as we process
${me}: the files.
${me}: -v or --verbose List the filenames we process, as we process
${me}: the files.
${me}: -n or --noaction Don't actually execute the commands. Used in
${me}: connection with --debug for testing.
${me}: -r or --remove Remove the input file unless --debug is set.
EOF
exit 2
}
declare -i debug=0 verbose=0 noaction=0 remove=0
# from /usr/share/doc/util-linux/examples/getopt-parse.bash 2015-Sep-06
TEMP=$(getopt -o dhvnr --long debug,help,verbose,noaction,remove \
-n 'fixthem.bash' -- "$@")
if [[ $? != 0 ]] ; then echo "${me} --help for help." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true ; do
case "$1" in
-d|--debug) debug=1; shift;;
-h|--help) help; shift;;
-v|--verbose) verbose=1; shift;;
-n|--noaction) noaction=1; shift;;
-r|--remove) remove=1; shift;;
--) shift; break;;
*) echo "Internal error! ${me} --help for help";exit 1;;
esac
done
# actual processing begins here
while [[ $# -gt 0 ]] ; do
infile="$1"
shift
nameonly="${infile%.*}"
outfile="${nameonly}.mp4"
[[ "$verbose" -ne 0 ]] && echo "$infile -> $outfile" >&2
command="ffmpeg -i \"$infile\" -vcodec copy -acodec copy \"$outfile\""
[[ "$debug" -ne 0 ]] && echo "command" >&2
[[ "$noaction" -ne 0 ]] || eval "$command"
if [[ "$remove" -ne 0 ]] ; then
v=""
[[ "$verbose " -ne 0 ]] && v="-v"
if [[ "$debug" -ne 0 ]] ; then
echo "rm \"$infile\"" >&2
else
rm $v "$infile"
fi
fi
done
exit 0
Si vous souhaitez conserver votre syntaxe existante (ce qui a probablement du sens pour vous telle qu'elle est), la légère modification suivante devrait conserver ce sens pendant que aussi accomplit le changement de nom de fichier requis:
find -iname '*.avi' -o -iname '*.mkv' -exec \
bash -c 'ffmpeg -i "{}" -codec copy \
$(echo "{}" | sed -r 's/.{3}$/mp4/')' \;
Notez que j'ai aussi simplifié votre syntaxe copy
avec FFmpeg ...