0

I'm currently trying to write a little script to convert all the flac files to mp3 files. However, I ran into a bit of a problem when trying to set up recursion down into all my music folders - the script kept looping into the current directory (.)

Here's what I currently have:

#!/bin/bash

#---
# flacToMp3: Converts FLAC files in my originalFLAC folder into mp3 files
#            and places them in an identical folder structure in my Music
#            folder.
#---

function enterDIR {
    for DIR in "$(find . -maxdepth 1 -type d)"; do #recurse into every directory below top-level directory
        if [ "$DIR" == "." ]; then  #avoid current directory infinite loop
            continue
        fi
        cd "$DIR/"
        enterDIR
    done

    createDirectory
    convertFLAC
}

function createDirectory {
    #recreate directory structure in Music folder
    curDir="$pwd"
    newDir=${curDir/originalFLAC/Music}
    mkdir -p $newDir
}

function convertFLAC {
    #convert each flac file in current directory into an mp3 file
    for FILE in "$(find . -maxdepth 1 -type f)"; do #loop through all regular (non-directory) files in current directory
        if [ "${FILE: -5}" == ".flac" ]; then #if FILE has extension .flac
            ffmpeg -i "$FILE" -ab 320k -map_metadata 0 "${FILE%.*}.mp3"; #convert to .mp3
            mv -u "${FILE%.*}.mp3" $newDir
        else #copy all other files to new directory as-is
            cp -ur "$FILE" $newDir
        fi
    done
}

enterDIR

This script is pretty clunky, since I only just started dipping into Bash. The problem (or at least where I think it is) comes from the if [ "$DIR" == "." ]; then line - looking at my output when running the script, it doesn't seem to filter it.

How do I filter out (ignore) the current directory?

  • One = for [ ... – Jeff Schaller Jan 22 '16 at 15:31
  • Can't you use something like find . -maxdepth 1 -name "*.flac"? – pfnuesel Jan 22 '16 at 15:33
  • 1
    You'll want to read mywiki.wooledge.org/BashFAQ/001 -- don't use for to iterate over lines. – glenn jackman Jan 22 '16 at 15:34
  • I think find . -type f -name "*.flac" would suffice. Let find delve into your directories. – glenn jackman Jan 22 '16 at 15:36
4

You can filter it in find by using -mindepth option. Like this:

function enterDIR {
    find . -mindepth 1-maxdepth 1 -type d | while read DIR ; 
    do 
        #recurse into every directory below top-level directory
        cd "$DIR/"
        enterDIR
    done

    createDirectory
    convertFLAC
}

But the whole script doesn't look like a good solution.

If I understand your idea correct, you want to walk through the whole directory tree, create there new directory, convert flac to mp3 if any and copy all non-flac files to a new dir. I would do that this way:

find . -mindepth 1 -type -d -exec mkdir -p {}/originalFLAC/Music \+
find . -type f -iname "*.flac" -exec ffmpeg -i {} -ab 320k -map_metadata 0 {}.mp3 \;
find . -type f ! -iname "*.flac" | while read file ; do cp -v "$file" "$(dirname "$file")"/originalFLAC/Music/ ; done
  • +1 for giving the actual solution: using find for what it's for and not recurse manually into the directories. – lgeorget Jan 22 '16 at 15:50
  • Please demonstrate good practices: mywiki.wooledge.org/DontReadLinesWithFor – glenn jackman Jan 22 '16 at 15:56
  • I realize that, but you could take that one extra step – glenn jackman Jan 22 '16 at 16:00
  • well, maybe you're right. thx for comment. answer is updated. – rush Jan 22 '16 at 16:01
  • 1
    ! means not. therefore find . -type f ! -iname "*.flac" means find all files with name not matching to .flac (i before name means case insensitive) – rush Jan 22 '16 at 16:10
-1

try replacing this

for DIR in "$(find . -maxdepth 1 -type d)"

with this

for DIR in "$(find . -maxdepth 1 -type d | grep -v "\.$")"

. is interpreted as "any" single character in regex. So it has to be escaped with backslash. Also since all your lines will start with a dot character, you will need to find the line that has the dot and only the dot. Hence the end of line character $.

at this point, you should not need the if block below:

if [ "$DIR" == "." ]; then  #avoid current directory infinite loop
    continue
fi
  • find . -maxdepth 1 -type d -not -name . – glenn jackman Jan 22 '16 at 15:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.