[SOLVED] Bash case-esac alternatives and optimization for empty and set variable combinations
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Distribution: Slackware_x64 15.0 and slackware-current
Posts: 33
Rep:
Bash case-esac alternatives and optimization for empty and set variable combinations
Below is a piece of working code in a much larger program that basically renames directories containing music files before performing some other tasks.
My question is if there is a way to optimize this using less code, a case-esac block or any other methods I haven't thought about?
Any suggestions on how to tighten up the code for the debugger is also welcomed. Thanks in advance
Code:
find -type d -maxdepth 1 | while read R; # loop through album directories to get mp3 names
DNAME=$R
#
# gathered release date, recorded date, album name, and bitrate from one audio file in directory using mediainfo
# if mediainfo can't find an album name, I aborted during the gathering phase to prevent strange directory names
#
NEWDIRNAME=$DIRRELEASED.$DIRALBUM.$DIRRATE # Desired directory name = [ -n "$DIRRELEASED" ] && [ -n "$DIRALBUM" ] && [ -n "$DIRRATE" ]
if [ "$NEWDIRNAME" != "$DNAME" ] # only execute code if the new name is different than existing name - first check
then
if [ -z "$DIRRELEASED" ] && [ -z "$DIRRECORDED" ] && [ -n "$DIRALBUM" ] && [ -z "$DIRRATE" ]
then
NEWDIRNAME=$DIRALBUM
fi
if [ -n "$DIRRELEASED" ] && [ -n "$DIRALBUM" ] && [ -z "$DIRRATE" ]
then
NEWDIRNAME=$DIRRELEASED.$DIRALBUM
fi
if [ -z "$DIRRELEASED" ] && [ -z "$DIRRECORDED" ] && [ -n "$DIRALBUM" ] && [ -n "$DIRRATE" ]
then
NEWDIRNAME=$DIRALBUM.$DIRRATE
fi
if [ -z "$DIRRELEASED" ] && [ -n "$DIRRECORDED" ] && [ -n "$DIRALBUM" ] && [ -n "$DIRRATE" ]
then
NEWDIRNAME=$DIRRECORDED.$DIRALBUM.$DIRRATE
fi
if [ -z "$DIRRELEASED" ] && [ -n "$DIRRECORDED" ] && [ -n "$DIRALBUM" ] && [ -z "$DIRRATE" ]
then
NEWDIRNAME=$DIRRECORDED.$DIRALBUM
fi
#
if [ "$DEBUG" = "debug" ]
then
if [ "$NEWDIRNAME" != "$DNAME" ] # only execute code if the new name is different than existing name - final check after gathering and updating
then
mv -v -f $DNAME $NEWDIRNAME | tee -a $DEBUGLOG $RENAMELOG
else
echo "directory $DNAME doesn't need renaming" | tee -a $DEBUGLOG $RENAMELOG
fi
else
if [ "$NEWDIRNAME" != "$DNAME" ] # only execute code if the new name is different than existing name - final check after gathering and updating
then
mv -v -f $DNAME $NEWDIRNAME | tee -a $RENAMELOG
else
echo "directory $DNAME doesn't need renaming" | tee -a $DEBUGLOG $RENAMELOG
fi
fi
else
if [ "$DEBUG" = "debug" ]
then
echo "directory $DNAME doesn't need renaming" | tee -a $DEBUGLOG $RENAMELOG
else
echo "directory $DNAME doesn't need renaming" | tee -a $RENAMELOG
fi
fi
Last edited by rwyarbrough; 10-26-2018 at 06:52 PM.
Distribution: Slackware_x64 15.0 and slackware-current
Posts: 33
Original Poster
Rep:
Quote:
Originally Posted by BW-userx
here is one way I've moved my mp3 renaming the dir/sub-dir by meta tags, its old bash code, but it works.
Thanks! I have a script that performs mkvnixtool operations on recursive directories so I can have consistency ( and fancy titles) with my TV_show downloads - fun stuff!
Quote:
Originally Posted by BW-userx
it can get harry doing this, these are my less elaborate ones.
Take a peek at this... ( debugger code removed to reduce length of post - you're welcome very much! <grin>
The reasoning for all this is that I like to include the bitrate information in the directory and file names. This only works with compressed audio, so I just use the extension in place of the bitrate in the directory/filename for uncompressed, Lossless, and unknown file types.
Code:
AUDIOFORMATS=(.3gp .aa .aac .aax .act .aiff .amr .ape .au .awb .bwf .dct .dss .dvf .flac .gsm .iklax .ivs .m4a .m4b .m4p .mmf .mp3 .mpc .msv .nsf .ogg .oga .mogg .opus .pcm .ra .rm .raw .sln .tta .vox .wav .wma .wv .webm .8svx)
# Audio Types - X = unknown or excluded C = Compressed L = Lossless U = Uncompressed
AUDIOFORMATTYPES=(X X C X X U X L U X L X X X L X X X C C C X C C X X C X X X U X X U X X X U C X C X)
function buildaudioformatfind()
{
# build audio file type array
for i in "${!AUDIOFORMATTYPES[@]}"
do
if [[ "${AUDIOFORMATTYPES[$i]}" = "C" ]]
then
COMPRESSEDAUDIO=("${COMPRESSEDAUDIO[@]}" "${AUDIOFORMATS[$i]}")
else
UNCOMPRESSEDAUDIO=("${UNCOMPRESSEDAUDIO[@]}" "${AUDIOFORMATS[$i]}")
fi
done
# creating find strings from audio file type arrays created above
for index in ${!COMPRESSEDAUDIO[@]}
do
FINDVAR=(${FINDVAR[@]} $(printf '%s \"*%s\" %s' "-name" ${COMPRESSEDAUDIO[$index]} "-o") )
L=$(echo ${#FINDVAR[@]})
FINDSTRING=$(echo ${FINDVAR[@]:0:$L} | sed 's/\(.*\)-o.*/\1/')
done
for index in ${!UNCOMPRESSEDAUDIO[@]}
do
FINDVARU=(${FINDVARU[@]} $(printf '%s \"*%s\" %s' "-name" ${UNCOMPRESSEDAUDIO[$index]} "-o") )
L=$(echo ${#FINDVARU[@]})
FINDSTRINGU=$(echo ${FINDVARU[@]:0:$L} | sed 's/\(.*\)-o.*/\1/')
done
FINDVARFULL=(${FINDVAR[@]} ${FINDVARU[@]})
L=$(echo ${#FINDVARFULL[@]})
FINDSTRINGFULL=$(echo ${FINDVARFULL[@]:0:$L} | sed 's/\(.*\)-o.*/\1/')
}
Last edited by rwyarbrough; 10-26-2018 at 10:02 PM.
I think you're missing the dodone for the while loop actually.
Quote:
My question is if there is a way to optimize this using less code, a case-esac block or any other methods I haven't thought about?
So if I understand correctly, you have 4 variables, and you want to join them together with dots in between, leaving out empty variables. I would go with something like this:
Take a peek at this... ( debugger code removed to reduce length of post - you're welcome very much! <grin>
Just some general comments
Code:
ARRAY_VAR=("${ARRAY_VAR[@]}" "$VALUE")
# can be written
ARRAY_VAR+=("$VALUE")
for i in ${!ARRAY_VAR[@]}
... ${ARRAY_VAR[i]} ...
# can be written
for elem in "${ARRAY_VAR[@]}"
... $elem ...
L=$(echo ${#FINDVAR[@]})
# is just
L=${#FINDVAR[@]}
Your code does not handle case when DIRALBUM is not set so I’m assuming that it’s always set. There are a few other approaches:
Code:
NEWDIRNAME=${DIRRELEASED:-DIRRECORDED}.$DIRALBUM.$DIRRATE
NEWDIRNAME=${NEWDIRNAME#.} # remove leading dot if date is missing
NEWDIRNAME=${NEWDIRNAME%.} # remove leading dot if bitrate is missing
@rwyarbrough, how do you scrape your mp3's to get the meta data off it, album, artist, title? using exiftool I have to run that over the mp3 for each tag, which means three times or more depending on meta data tag info I am trying to get. I was wondering what it your method, if it is more economical.
Distribution: Slackware_x64 15.0 and slackware-current
Posts: 33
Original Poster
Rep:
Quote:
Originally Posted by BW-userx
@rwyarbrough, how do you scrape your mp3's to get the meta data off it, album, artist, title?
For the directory renaming, I use mediainfo https://mediaarea.net/en/MediaInfo - Multiplatform - quite a nice program. it has quite a few fields, but you can run it once and parse the desired fields.
example output
Quote:
>$ mediainfo 14_Enigma_Variationen_-_XIII.Romanza-_---_Moderato.mp3
General
Complete name : 14_Enigma_Variationen_-_XIII.Romanza-_---_(Moderato).mp3
Format : MPEG Audio
File size : 6.44 MiB
Duration : 2 min 48 s
Overall bit rate mode : Constant
Overall bit rate : 320 kb/s
Album : Enigma Variation & Pomp and Circumstance op39
Album/Performer : Edwin Elgar
Track name : Enigma Variationen - XIII.Romanza: *** (Moderato)
Track name/Position : 14
Performer : Edwin Elgar
Genre : classical
Recorded date : 1985
Writing library : LAME3.99r
Audio
Format : MPEG Audio
Format version : Version 1
Format profile : Layer 3
Format settings : Joint stereo
Mode : Joint stereo
Duration : 2 min 48 s
Bit rate mode : Constant
Bit rate : 320 kb/s
Channel(s) : 2 channels
Sampling rate : 44.1 kHz
Compression mode : Lossy
Stream size : 6.43 MiB (100%)
Writing library : LAME3.99r
Encoding settings : -m j -V 4 -q 3 -lowpass 20.5
For the actual file renaming, I use filebot (which I think also uses mediainfo as a call)
pi.pad(2) = track number padded to 2 digits
t.space('_') = Track Name with spaces replaced by underscores (along with other replacements)
$media.OverallBitrateString = overall bite rate
media.overallBitrateString will return the kbps value of the digital recording unless its a variable bitrate digital recording which will return "null", so I replace null with the word variable.
filebot rename code
Code:
# file renaming starts here
#Track name
CNT=0
for f in ${COMPRESSEDFILESARRAY[*]}
do
CNT=$(( CNT + 1 ))
if [ "$DEBUG" = "debug" ]
then
echo "renaming with command: filebot -rename $f --format \"{pi.pad(2)}.{t.space('_').replaceAll(/&/,\"and\").replaceAll(/#/,\"number\").replaceAll(\"[^a-zA-ZÀ-ÿ0-9_-]\", \"\")}{\".\$media.OverallBitrateString\".replaceAll(/null/, \"variable\").replaceAll(/ kb\/s/,\"\")}\" --db $DBID >> $DEBUGLOG" >> $DEBUGLOG
filebot -rename $f --format "{pi.pad(2)}.{t.space('_').replaceAll(/&/,\"and\").replaceAll(/#/,\"number\").replaceAll(\"[^a-zA-ZÀ-ÿ0-9_-]\", \"\")}{\".\$media.OverallBitrateString\".replaceAll(/null/, \"variable\").replaceAll(/ kb\/s/,\"\")}" --db $DBID >> $DEBUGLOG
echo "the filename is = $f" >> $DEBUGLOG
else
filebot -rename $f --format "{pi.pad(2)}.{t.space('_').replaceAll(/&/,\"and\").replaceAll(/#/,\"number\").replaceAll(\"[^a-zA-ZÀ-ÿ0-9_-]\", \"\")}{\".\$media.OverallBitrateString\".replaceAll(/null/, \"variable\").replaceAll(/ kb\/s/,\"\")}" --db $DBID >> $RENAMELOG
fi
fcut=$(echo ${f##*/} | cut -c -30)
printf "\r%b" "\033[2K"
printf "%3d %% completed - %5d of %5d - %s" "$(($CNT*100/$AUDIODIRCOUNT))" "$CNT" "$AUDIODIRCOUNT" "$fcut"
#echo -en "$(($CNT*100/$AUDIODIRCOUNT))% completed - $CNT of $AUDIODIRCOUNT - $fcut \r"
done
# uncompressed starts here
echo -e "\n************************************************************"
echo -e "\nthis run for uncompressed audio files"
echo "There are $AUDIODIRCOUNTU uncompressed audio files in $dircountu uncompressed audio music type directories(s) to go through music file renaming in directory $(pwd)"
echo -e "************************************************************"
if [ "$DEBUG" = "debug" ]
then
echo AUDIODIRCOUNTU=$AUDIODIRCOUNTU >> $DEBUGLOG
echo countleft=$countleft >> $DEBUGLOG
echo dircountu=$dircountu >> $DEBUGLOG
echo totalcountleft=$totalcountleft >> $DEBUGLOG
echo -e "\n************************************************************" >> $DEBUGLOG
echo -e "\nthis run for uncompressed audio files" >> $DEBUGLOG
echo "There are $AUDIODIRCOUNTU compressed audio files in $dircountu compressed audio music type directories(s) to go through music file renaming in directory $(pwd)" >> $DEBUGLOG
echo -e "************************************************************" >> $DEBUGLOG
fi
echo -e "\n************************************************************" >> $RENAMELOG
echo -e "\nthis run for uncompressed audio files" >> $RENAMELOG
echo "There are $AUDIODIRCOUNTU uncompressed audio files in $dircountu compressed audio music type directories(s) to go through music file renaming in directory $(pwd)" >> $RENAMELOG
echo -e "************************************************************" >> $RENAMELOG
# file renaming starts here
CNT=0
for f in ${UNCOMPRESSEDFILESARRAY[*]}
do
CNT=$(( CNT + 1 ))
AUDIOFILEEXT=${f##*.}
if [ "$DEBUG" = "debug" ]
then
echo "renaming with command: filebot -rename $f --format \"{pi.pad(2)}.{t.space('_').replaceAll(/&/,\"and\").replaceAll(/#/,\"number\").replaceAll(\"[^a-zA-ZÀ-ÿ0-9_-]\", \"\")}\" --db $DBID >> $DEBUGLOG" >> $DEBUGLOG
filebot -rename $f --format "{pi.pad(2)}.{t.space('_').replaceAll(/&/,\"and\").replaceAll(/#/,\"number\").replaceAll(\"[^a-zA-ZÀ-ÿ0-9_-]\", \"\")}" --db $DBID >> $DEBUGLOG
echo "the filename is = $f" >> $DEBUGLOG
else
filebot -rename $f --format "{pi.pad(2)}.{t.space('_').replaceAll(/&/,\"and\").replaceAll(/#/,\"number\").replaceAll(\"[^a-zA-ZÀ-ÿ0-9_-]\", \"\")}" --db $DBID >> $RENAMELOG
fi
fcut=$(echo ${f##*/} | cut -c -30)
printf "\r%b" "\033[2K"
printf "%3d %% completed - %5d of %5d - %s" "$(($CNT*100/$AUDIODIRCOUNTU))" "$CNT" "$AUDIODIRCOUNTU" "$fcut"
#echo -en "$(($CNT*100/$AUDIODIRCOUNTU))% completed - $CNT of $AUDIODIRCOUNTU - $fcut \r"
done
Last edited by rwyarbrough; 10-31-2018 at 06:10 PM.
For the directory renaming, I use mediainfo https://mediaarea.net/en/MediaInfo - Multiplatform - quite a nice program. it has quite a few fields, but you can run it once and parse the desired fields.
example output
For the actual file renaming, I use filebot (which I think also uses mediainfo as a call)
pi.pad(2) = track number padded to 2 digits
t.space('_') = Track Name with spaces replaced by underscores (along with other replacements)
$media.OverallBitrateString = overall bite rate
media.overallBitrateString will return the kbps value of the digital recording unless its a variable bitrate digital recording which will return "null", so I replace null with the word variable.
thanks, looks interesting, I'll give it a look through when I get a chance.
Distribution: Slackware_x64 15.0 and slackware-current
Posts: 33
Original Poster
Rep:
Quote:
Originally Posted by mina86
Your code does not handle case when DIRALBUM is not set so I’m assuming that it’s always set
There is a check earlier not shown in the code block where if DIRALBUM is null, then I abort and move to the next record as there is no sense doing anything else if I can't get the album name from the tags.
Quote:
Originally Posted by mina86
Code:
NEWDIRNAME=${DIRRELEASED:-DIRRECORDED}.$DIRALBUM.$DIRRATE
NEWDIRNAME=${NEWDIRNAME#.} # remove leading dot if date is missing
NEWDIRNAME=${NEWDIRNAME%.} # remove leading dot if bitrate is missing
Great stuff - that is what I was looking for. Your next code example however looks the leanest and meanest and is what I will undoubtedly use in place of all my if/else statements...
THAT'S IT!! That is the solution - removing the leading dot was where I was having all of my problems. Didn't know how to handle that without some type of if/else statement. Thank you so much for that! Marking this as SOLVED based on this post.
Last edited by rwyarbrough; 11-01-2018 at 07:17 AM.
Distribution: Slackware_x64 15.0 and slackware-current
Posts: 33
Original Poster
Rep:
Quote:
Originally Posted by ntubski
I think you're missing the dodone for the while loop actually.
More than likely I am - that was a copy/paste from a much larger code block
Quote:
Originally Posted by ntubski
So if I understand correctly, you have 4 variables, and you want to join them together with dots in between, leaving out empty variables.
Exactly. My initial problem was having null values, but still printing the dots, so I'd end up with either a dot as the first character, or two dots in the filename (release.album..mp3 for example)
Thanks for you suggestions and comments. They were helpful.
Last edited by rwyarbrough; 11-01-2018 at 07:00 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.