madpoet
madpoet

Reputation: 1063

Cannot escape path in bash file

I'm trying to run some command with looping through all files in a directory. The code is:

#!/bin/bash
shopt -s nullglob
INPUT_DIR=$1
OUTPUT_DIR=$2

: ${INPUT_DIR:="."}
: ${OUTPUT_DIR:="."}

files="$INPUT_DIR/*.ttf"

for file in $files
do
    base_file=${file##*/}
    output="$OUTPUT_DIR/${base_file%.*}.woff"
    ttf2woff "$file" "$output" || exit 1
done

I'd expect the double qoutes around $INPUT_DIR/*.ttf would do the magic but apparently it's not:

$> ttf2woff_multi "/Users/ozan/Dropbox/Graphic Library/Google Fonts/fonts-master/ofl/raleway"
Can't open input file (/Users/ozan/Dropbox/Graphic)

and when I print out $FILES I get: /Users/ozan/Dropbox/Graphic Library/Google

What am I missing here?


Edit: files="$INPUT_DIR"/*.ttf instead of files="$INPUT_DIR/*.ttf" doesn't work either...

Upvotes: 0

Views: 159

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84652

In addition to the array solution, (which is a good solution), you can also make use of read with process substitution:

INPUT_DIR=${1:=.}
OUTPUT_DIR=${2:=.}

[ -d "$INPUT_DIR" -a -d "$OUTPUT_DIR" ] || {
    printf "error: invalid directory specified (INPUT_DIR or OUTPUT_DIR)\n"
    exit 1
}

while IFS= read -r file; do
    base_file=${file##*/}
    output="$OUTPUT_DIR/${base_file%.*}.woff"
    ttf2woff "$file" "$output" || exit 1
done < <(find "$INPUT_DIR" -type f -iname "*.ttf")

Upvotes: 1

fedorqui
fedorqui

Reputation: 290515

Since you want to loop through a list of files, better store them in an array:

files=("$INPUT_DIR"/*.ttf)

for file in "${files[@]}"
do
    base_file=${file##*/}
    output="$OUTPUT_DIR/${base_file%.*}.woff"
    ttf2woff "$file" "$output" || exit 1
done

Note you were saying "$INPUT_DIR/*.ttf" whereas I am suggesting "$INPUT_DIR"/*.ttf. This is to allow the globbing to behave as intended and expand properly.


The key point here, as Cyrus mentions in comments, is the fact of not quoting, since they prevent globbing.

See an example with some files.

$ ls f*
f1  f2  f3

Store with double quotes... it just matches the string itself:

$ files=("f*")
$ for f in "${files[@]}"; do echo "$f"; done
f*

See how it is expanded if we do not quote:

$ files=(f*)
$ for f in "${files[@]}"; do echo "$f"; done
f1
f2
f3

Upvotes: 0

Related Questions