3

I'm working on a Bash script that will take an array of directories, iterate through it, create a directory named "processed" inside each directory, and run a command on each file within the directory. Here's my code (read the comment in the code to see what I'm stuck on). Any ideas?

#!/bin/bash

command -v convert >/dev/null 2>&1 || {
    echo >&2 "Convert is not installed. Aborting.";
    exit 1;
}

declare -a directories_to_process=(
    "$HOME/Desktop/Album 1"
    "$HOME/Desktop/Album 2"
    "$HOME/Desktop/Album 3"
);

for directory in "${directories_to_process[@]}"
do
    if [ -d "$directory" ]; then
        if [ ! -d "$directory/processed" ]; then
            mkdir "$directory/processed"
        fi

        # Insert code to run the following command on each file in $directory:
        #
        # convert $directory/$filename -resize 108x108^ -gravity center -extent 108x108 $directory/processed/$filename
    fi
done

UPDATE:

Here is the working script:

#!/bin/bash

command -v convert >/dev/null 2>&1 || {
    echo >&2 "Convert is not installed. Aborting.";
    exit 1;
}

directories_to_process=(
    "$HOME/Desktop/Album 1"
    "$HOME/Desktop/Album 2"
    "$HOME/Desktop/Album 3"
);

for directory in "${directories_to_process[@]}"
do
    [[ -d $directory ]] || continue

    mkdir -p "$directory/processed"

    for infile in "$directory"/*.jpg
    do
        outfile="$directory/processed/${infile##*/}"
        convert "$infile" \
                -resize '108x108^' \
                -gravity center \
                -extent 108x108 \
                "$outfile"
    done
done
Nick
  • 8,049
  • 18
  • 63
  • 107

1 Answers1

2

Add this in the commented-out area:

for infile in "$directory"/*; do
  outfile="$directory/processed/${infile##*/}"
  convert "$infile" \
      -resize '108x108^' \
      -gravity center \
      -extent 108x108 \
      "$outfile"
done

A few other notes:

  • Instead of nesting a great deal of logic inside of if [ -d "$directory" ], consider putting [[ -d $directory ]] || continue at the top of the loop to reduce the nesting depth. (Unlike [ ], quoting is not needed inside [[ ]] in this case).
  • Instead of testing [ ! -d "$directory/processed" ] and using that to decide whether to create the directory, consider unconditionally running mkdir -p "$directory/processed", which will simply exit with a successful status if the directory already exists.
  • Consider replacing command -v convert with type convert, which is somewhat better known than the command -v syntax but will have the same effect.
  • You don't need the declare -a when declaring an array variable outside of a function; simply directories_to_process=( ... ) will work.
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Quoting the whole glob won't work. Change it to `for infile in "$directory"/*; do` – Dennis Williamson May 30 '12 at 01:42
  • @DennisWilliamson Ugh -- I know better than that. Thank you for the catch. – Charles Duffy May 30 '12 at 11:19
  • @CharlesDuffy That works! Thank you very much for not only answering my question, but providing tips for improvement. You're awesome! See my question for the final script I used. I stuck with `command -v` because, according to [this](http://stackoverflow.com/a/677212/937084), `command`'s exit status is well defined by POSIX, so that one is probably the safest to use. – Nick May 30 '12 at 15:39
  • Note: if you use this as a standalone script, remember to create `processed` first, or you get unhelpful errors. – GKFX Dec 28 '14 at 20:43