Resample flac bash script, need help?

Hello All,
I am running out of disk space and want to batch process a directory full of 24/96 & 25/192 flac files to bring the size down. The following script is what I am trying but it fails miserably. I would like it to resample the flacs and put them in a folder named with artist album in either my home directory or better still my /media/storage directory. I am not a coder but have been trying for too long to get this to work so I thought I would post here. Here is the code I am trying:

#!/bin/bash

# Recursively find FLAC files starting in current directory
find -name *.flac | while read FLACFILE
  do
    # Grab the id3 tags from the FLAC file
    ARTIST=`metaflac "$FLACFILE" --show-tag=ARTIST | sed s/.*=//g`
    TITLE=`metaflac "$FLACFILE" --show-tag=TITLE | sed s/.*=//g`
    ALBUM=`metaflac "$FLACFILE" --show-tag=ALBUM | sed s/.*=//g`
    GENRE=`metaflac "$FLACFILE" --show-tag=GENRE | sed s/.*=//g`
    TRACKNUMBER=`metaflac "$FLACFILE" --show-tag=TRACKNUMBER | sed s/.*=//g`
    DATE=`metaflac "$FLACFILE" --show-tag=DATE | sed s/.*=//g`
 
    FILENAME=`echo ${FLACFILE##*/}`
 
    # output path and rename the file
    FLACFILE=`echo "/home/$USER/Music/$ARTIST/$ALBUM/$FILENAME" | sed s/.flac$/.flac/g`
        
   sox -S -D -b 24 $FLACFILE rate -v -b 99 48k 
   -a "$ARTIST" -t "$TITLE" -l "$ALBUM" -G "GENRE" -N "$TRACKNUMBER" -d "$DATE" "$FLACFILE"
   done


# The script will end when the list of input files is
# exhausted.

I just can’t get it work, spaces in filenames, won’t make the folders ect ect. The sox command is how I think it should be. I played around with it on the command line and the spectrograms in Audacity look very nice after resampling to 24-48. All of the albums I am trying this with are either 24-96 or 24-192 and I am trying to go to 24-48 with all of them to get back some diskspace. Very frustrating, a horrible looking code job I know. Any help would be greatley appreciated. I was using Audacity to resample but I have too many albums to process and one by one would take me until next Christmas . Thanks in advance for any help.

Cheers,

Singtoh

Provided that there are no duplicate names, I think this should work:

#!/bin/bash

## Resample FLAC files

# Output directory
output="/home/<username>/processed-files"
if [ -d $output ]
  then echo "Folder already exists"
  else mkdir $output
fi

# start loop
find . -name '*.flac' | while IFS=$'n' read -r FILE
  do
    outputfile="$(basename "$FILE")"
    echo "Processing $outputfile"
    sox -S "$FILE" -r 48000 "$output/$outputfile"
    || echo "error processing: $FILE"

done

The metadata should be automatically carried across by SoX.
For 24 bit source files the output should automatically be 24 bit so no need to specify that and no need to disable dither as the bit format is not changing.

Hello Steve,

Thanks for the reply and also the code. I’ll give this a go when I get back to my computer. I’m sure this will work nicely, confidence is high! Thanks a bunch Steve, your always a great help:) :slight_smile:

Cheers,

Singtoh

Hello Steve,

Thank you very much for the help. I just tried this script and it works, but the only folder it makes is the “processed-files” folder in my home directory. So when I do a boatload of vinyl folders it throws the files into “processed-files” without folders of what album or artist they belong to. Sorry man, my brain isn’t wired to do this code stuff no matter how hard I try :blush:. The man page for mkdir isn’t very helpful to me. I can deal with it though, I just have to sort all the album files into folders manually which is better than what I was doing before. At least I can do several albums of the same artist this way without too much grief. :slight_smile: Thanks again for the help Steve, it is greatley appreciated :smiley:

Cheers,

Singtoh

Yes, I had a look at recreating the original folder structure in a new location but I couldn’t get it to work (I’m sure it’s possible but I’m no scripting expert :wink:)

It would be easy to change the script so that it just processes files in the folder that the script is in rather than recursive. In fact that’s a lot easier than making it recursive. I think it would then be quite easy for the script to make a folder in the target directory that has the same name as the current folder. Would that be easier to manage with your collection, or are you OK doing it with what you have now?

Wow Steve, you read my mind, I actually tried to process them into the same folder before but all I could get it to do was output the names of the tracks but they were all 3kb files so I gave up on that bit, and I was having to do albums one by one which is kind of a bummer. But, doing it as you suggested would mean that I have to process albums one by one??? or am I misunderstanding something?? I’ve got about 400 or more albums to process and was hoping I could just turn the script loose on the directory with say 50gigs worth of music at a time, and go drink beer, come back when its all done. I have about 100gig free space out of 1terabyte to play with so if I process it like that, I can then shift the originals to an external or something to free space on my machine. I’m OK with it the way it is now if there is no other alternative, I would rather process one artist directory of several to many albums at a time than one album at a time. Thanks too much for your help Steve :smiley:

Cheers,

Singtoh

It depends how your library is organised.
What I was suggesting was that you could process all of the files in one folder (directory) in one run.

The code that I posted will process all of the files in the current directory, and all of the files in sub-directories, sub-sub-directories, and so on (recursive).

How is your library organised? (what is the directory structure/hierarchy?)
Is it something like:
music/genre/artist/album/files

Oh, then that would be perfect I think. My music is all under one main folder/directory called rock, then under rock I have folders named A all the way to Z then under those folders comes the artist e.g ACDC is under A folder and under each artist folder comes all their albums with each album in its own folder, so I think what you suggested will work a treat:) if I understand correctly. Sounds like beer is in my near future then:) Thanks a bunch Steve:)

Cheers,

Singtoh

Sorry, I’m on my phone small screen and didn’t see your example. It is as you say /music/artist/albums/files.

Cheers

So the actual directory structure is like this?

/rock/(A-Z)/artist/album/files

With the current (recursive) code:
if you run the script from “/rock/” then it should resample the entire collection and put copies into the specified output directory (in the posted code that is: /home//processed-files)
If you run the script from "/rock/A/ then it should resample all albums that start with A and put copies into the specified output directory.
Whichever folder you run the script from, all files and folders from that folder down will be processed.

The above is probably not idea because you will end up with files from “High Voltage” and “Let there be Rock” all mixed up in the same output folder.

Non-recursive processing will process only the files in the current folder. Again that is not ideal because if you have 400 albums you will need to run the script 400 times.

Ideally I think that you would want to reproduce the file structure so that the output files go into:
/home//processed-files/rock/(A-Z)/artist/album/files
Unfortunately I’ve not got that to work yet.

Hello Steve,

Yes, its actually /media/Storage/processmusic/some-process-folder. All of my music sits in /media/Storage/Music/Rock/a/ACDC/ACDC-Let-there-be-rock/files along that pattern. I don’t do any processing on /home because that drive is only a 60gig ssd. Just thought I would try to clarify a little bit.

Cheers Steve,

Singtoh

I think this is what you want, but note that I am not a bash expert so use at your own risk.
Note also that this script must run in Bash and not in Dash.
Giving in a .sh extension, making it executable and then double clicking on the script file should work but if not run it from the command line with

bash filename

If you run it from “/rock/”
It should recreates an output folder at “/home//processed-files”
and then recreate “/home//processed-files/rock/(A-Z)/artist/album/files”
as it works through your collection.

#!/bin/bash

## Resample FLAC files

# Output directory
output="/home/<username>/processed-files"
if [ -d $output ]
  then echo "Folder already exists"
  else mkdir $output
fi

# start loop
find . -name '*.flac' | while IFS=$'n' read -r FILE
  do
    # Get file name and path
    outputfile="$(basename "$FILE")"
    DIR=$(dirname "$FILE")
    # Remove the leading dot and append to ouput path
    DIR=$output${DIR#.}

    # Create new folder if it does not exist
    if [[ ! -d $DIR ]]
    then
      mkdir -p $DIR
      echo "created"$DIR
    fi

    # Do the conversion
    sox -S "$FILE" -r 48000 "$DIR/$outputfile"
    || echo "error processing: $FILE"

done

Hello Steve,

Unfortunatley this does’t work for me either. As the script is now it makes directories under processed-files but the directories are like this: For example I have a folder called Ozzy Ozzbourne - Heaven & Hell - Vinyl - 2013. The script outputs one folder for each name in the filename, so one folder for Ozzy one folder for Ozzbourne one folder for “-” and so on with no output of sox(the script doesn’t actually run) I’ve played around with it a bit and got some different results all of which almost work kinda sorta but not really :blush: . I really am below novice material with this srcipting stuff. So, I really appreciate you trying to help me get this going but I don’t want to put you out any further :blush: . The way I have it now, the files all dump into one folder but the script renames the files to “Artist” “Album” “Track” to make it easier to idendify where they belong, and then I go into the folder after it finishes and make a boatload of un-named folders, highlight, drag and drop each album into a seperate folder and then go to puddletag and do a “tag > directory” and that renames all the folders to the album and artist as it should be. It’s kinda the shitz and would be good to have it run as we would like but I’ll manage like it is for now. Kinda surprised nobody else has chimed in with a solution but that’s just the way it goes I guess :wink: Again Steve, thanks for your efforts, it’s much appreciated :smiley:

Cheers,

Singtoh

I’ll just “tut” and shake my head slowly :wink:

I anticipated that you may have files with spaces in their names, but I didn’t anticipate spaces in the folder names - so now you know why geeks frown on using spaces in file names :smiley:
It’s not a big problem though - it just needs to directory to be quoted. I’ll post a new version in a few minutes.

Here it is: http://forum.audacityteam.org/download/file.php?id=7866

Ok sounds good Steve. You must be one of those “never say die” kind of guys :slight_smile: yeah, my bad with the spaces I guess but it just don’t seem rite without them. I won’t be near my computer until tomorrow sometime, but I’ll let you know how the new one works. Thanks again for your efforts:)

Cheers,

Singtoh

I’ve just run it on about 800 MB of FLAC files in a folder that includes sub-folders and sub-sub-folders and lots of n0n-FLAC files and it worked correctly.

I’d already done the hard bit (which took me ages, but I like solving problems :wink:) so it would have been a shame to leave it broken for such a silly detail.

If you’re interested, this is the bit that I changed:

    # Create new folder if it does not exist
    if [[ ! -d $DIR ]]
    then
      mkdir -p "$DIR"
      echo "created"$DIR
    fi

Previously it was: mkdir -p $DIR
but when bash evaluates $DIR it could be a string containing spaces.
For example, if: output=“/home/name/copied music/rock”
then $DIR ends up as: $DIR=/home/name/copied music/rock
so if it’s not quoted the mkdir command becomes:
mkdir -p /home/name/copied

Within double-quotes, “$”, “backquote”, and “the escape character” (usually “”) take their special meanings, so “$DIR” is read by bash as:
QUOTE QUOTE

Good Stuff Steve,

Yeah that did the trick, works perfectly now. Now I can just cut it loose on a directory and go drink some beers :sunglasses: Thanks so much for sticking with this until the winning moment and sorry for not mentioning the folders with spaces thing, maybe if I had it would have saved some grief :blush:

Cheers Steve,
All the best,

Singtoh

Excellent.

Let me know how that goes (the conversion I mean).
It would probably be a good idea if it also sent the stdout (standard output) to a log file. There is a Unix tee command that I think could take care of that.

No worries, I should have thought of that myself, but it does show that providing lots of detail at the start (something that we always urge people to do when asking questions on the forum) can help to solve the problem sooner.

Good luck with the big conversion, and have a beer for me :wink:

Hello Steve,

I just ran my first batch of 100gig 24-96 flacs and the script you provided ran without a problem. It made an exact replica of the originals, only at 24-48. You really saved me a bunch of jumping thru hoops with all the making folders and dragging and dropping and such. I gained about 50gigs back of hard disk so it’s all good man :smiley: Now I just have to reattach the artwork & reapply the replay-gain tags and this first batch is a done deal. Thanks again Steve, your super :smiley:, now for that beer I was bragging about :sunglasses:

Cheers,

Singtoh