I have a library of audio files organised as Audio/ArtistName/AlbumName/TrackName.ext
. Much of the metadata is incorrect and I want to use FFmpeg Metadata to correct all the files at once.
I found this post to execute a command on files within subfolders. I still require, however, the name of subfolder ArtistName
and the subfolder within AlbumName
to execute the command on each audio file:
ffmpeg -i inputfile -metadata artist="Subfolder Artist Name" -metadata album="Subfolder Album Name" outputfile
How can I edit the metadata of the files based on the names of the subfolders they are in?
Edit: I am trying to do this in Linux CLI or Bash Script. I am trying to go through folders (artist) and then the subfolders within (albums) and loop through the files and run a command based on the names value of artist folder and album subfolder. I have tried this to loop through the folders but it does not work for the subfolders within to execute a command on the files in the subfolders. I was able to return the artist and album name but I still cannot get the track name. cd
into the artist folder worked but not for the album folder
for artist in /tank/music/*/
do
art= basename "${artist}"
cd "${artist}"
for album in ./*/
do
alb= basename "${album}"
cd "${album}"
for track in ./*/
do
echo "${art}"
echo "${alb}"
echo "${track}"
done
done
done
If you cd
down a level, you have to cd
back out before you process another value at the same level.
I assume tracks are files and not directories.
Untested:
cd back out:
for artist in /tank/music/*/
do
art=$(basename "${artist}")
cd "${artist}"
for album in ./*/
do
alb=$(basename "${album}")
cd "${album}"
for track in *.ext
do
trk=$(basename "$track" .ext)
echo "${art}"
echo "${alb}"
echo "${trk}"
done
cd ..
done
cd ..
done
or use subshell so that cd out is implicit:
for artist in /tank/music/*/
do
art=$(basename "${artist}")
(
cd "${artist}"
for album in ./*/
do
alb=$(basename "${album}")
(
cd "${album}"
for track in *.ext
do
trk=$(basename "$track" .ext)
echo "${art}"
echo "${alb}"
echo "${trk}"
done
)
done
)
done
or just don't cd in the first place:
for artist in /tank/music/*/
do
art=$(basename "${artist}")
for album in "$artist"/*/
do
alb=$(basename "${album}")
for track in "$album"/*.ext
do
trk=$(basename "$track" .ext)
echo "${art}"
echo "${alb}"
echo "${trk}"
done
done
done
Alternative approaches:
# reduce typing
declare -n v=BASH_REMATCH
for f in /tank/music/*/*/*.ext; do
if [[ -f $f ]] && [[ $f =~ .+/(.+)/(.+)/(.+)".ext"$ ]]; then
echo "art=${v[1]} alb=${v[2]} trk=${v[3]}"
fi
done
cd /tank/music
unset a
for f in */*/*.ext; do
[[ -f $f ]] || continue
IFS=/ a=(${f%".ext"})
echo "art=${a[0]} alb=${a[1]} trk=${a[2]}"
done