Search code examples
linuxbashshellhandbrake

bash scripting, handling spaces in filesnames in a for loop strange behaviour


help. everything i've tried has failed. I'm trying to fix up my video collection and lots of them have spaces in the names/etc I want to transcode them and I've written the script below, but its failing. 2 of the filenames I'm using for testing are "13 Eerie (2013).avi" and "Ace.Ventura.When.Nature.Calls.1995.720p.WEB-DL.x264-mSD.mkv"

i have tried several things from using print0 on find to mangling the IFS. any assistance would be appreciated. This current version for some reasons separates everything on the e character


convert.sh

#!/bin/sh

OUTDIR="./done/"
LOGDIR="./logs/"
BACKUPDIR="./backup/"

# deal with spaces
SAVEIFS=$IFS
IFS=$(echo -en "\n")

# pull all files except MP4 or scripts in the CURRENT DIR only
for FULLFILENAME in `find . -maxdepth 1 -type f -not -iname "*.sh" -not -iname "*.mp4" -print`
do
    # extract the file extension
    filename=$(basename "$FULLFILENAME")
    ext="${filename##*.}"
    filename="${filename%.*}"

    # use handbrake to convert to x264
    HandBrakeCLI -i "$FULLFILENAME" -o "$OUTDIR$filename.mp4" -e x264 -q 22 -r 29.97 -B 64 -O 2>$LOGDIR$filename.log

    # move the original file to a backup
    mv "$FULLFILENAME" $BACKUPDIR
done

#restore the field separator
IFS=$SAVEIFS

Solution

    • Don't use command substitution of find
    • Don't use for loop
    • Use process substitution to get output from find
    • Use -print0 option and read using while loop
    • Better to avoid uppercase variable names
    • Use bash shebang

    Code:

    #!/bin/bash
    
    outdir="./done/"
    logdir="./logs/"
    backupdir="./backup/"
    
    
    # pull all files except MP4 or scripts in the CURRENT DIR only
    while IFS= read -r -d '' fullfilename
    do
        # extract the file extension
        filename="$(basename "$fullfilename")"
        ext="${filename##*.}"
        filename="${filename%.*}"
    
        # use handbrake to convert to x264
        HandBrakeCLI -i "$fullfilename" -o "$outdir$filename.mp4" -e x264 -q 22 -r 29.97 -B 64 -O 2>"$logdir$filename.log"
    
        # move the original file to a backup
        mv "$fullfilename" "$backupdir"
    done < <(find . -maxdepth 1 -type f -not -iname "*.sh" -not -iname "*.mp4" -print0)