2

I have a bash script which downloads images from Google Images.

This is the command I use:

bash getimages.sh 3 rocky%20mountains

That command will download the 3rd picture in Google Images. To download the first 10 pictures of the Rocky Mountains in Google Image Search I use the following amateurish command:

bash getimages.sh 1 rocky%20mountains && \
    bash getimages.sh 2 rocky%20mountains && \
    bash getimages.sh 3 rocky%20mountains && \
    bash getimages.sh 4 rocky%20mountains && \
    bash getimages.sh 5 rocky%20mountains && \
    bash getimages.sh 6 rocky%20mountains && \
    bash getimages.sh 7 rocky%20mountains && \
    bash getimages.sh 8 rocky%20mountains && \
    bash getimages.sh 9 rocky%20mountains && \
    bash getimages.sh 10 rocky%20mountains

I want a For Loop incorporated into the bash script so that it will download 20 images of a designated search term.

Bash Script:

#! /bin/bash

# function to create all dirs til file can be made
function mkdirs {
    file="$1"
    dir="/"

    # convert to full path
    if [ "${file##/*}" ]; then
        file="${PWD}/${file}"
    fi

    # dir name of following dir
    next="${file#/}"

    # while not filename
    while [ "${next//[^\/]/}" ]; do
        # create dir if doesn't exist
        [ -d "${dir}" ] || mkdir "${dir}"
        dir="${dir}/${next%%/*}"
        next="${next#*/}"
    done

    # last directory to make
    [ -d "${dir}" ] || mkdir "${dir}"
}

# get optional 'o' flag, this will open the image after download
getopts 'o' option
[[ $option = 'o' ]] && shift

# parse arguments
count=${1}
shift
query="$@"
[ -z "$query" ] && exit 1  # insufficient arguments

# set user agent, customize this by visiting http://whatsmyuseragent.com/
useragent='Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0'

# construct google link
link="www.google.com/search?q=${query}\&tbm=isch"

# fetch link for download
imagelink=$(wget -e robots=off --user-agent "$useragent" -qO - "$link" | sed 's/</\n</g' | grep '<a href.*\(png\|jpg\|jpeg\)' | sed 's/.*imgurl=\([^&]*\)\&.*/\1/' | head -n $count | tail -n1)
imagelink="${imagelink%\%*}"

# get file extention (.png, .jpg, .jpeg)
ext=$(echo $imagelink | sed "s/.*\(\.[^\.]*\)$/\1/")

# set default save location and file name change this!!
dir="$PWD"
file="google image"

# get optional second argument, which defines the file name or dir
if [[ $# -eq 2 ]]; then
    if [ -d "$2" ]; then
        dir="$2"
    else
        file="${2}"
        mkdirs "${dir}"
        dir=""
    fi
fi   

# construct image link: add 'echo "${google_image}"'
# after this line for debug output
google_image="${dir}/${file}"

# construct name, append number if file exists
if [[ -e "${google_image}${ext}" ]] ; then
    i=0
    while [[ -e "${google_image}(${i})${ext}" ]] ; do
        ((i++))
    done
    google_image="${google_image}(${i})${ext}"
else
    google_image="${google_image}${ext}"
fi

# get actual picture and store in google_image.$ext
wget --max-redirect 0 -qO "${google_image}" "${imagelink}"

# if 'o' flag supplied: open image
[[ $option = "o" ]] && gnome-open "${google_image}"

# successful execution, exit code 0
exit 0
2

Why do you want to incorporate it in the script when you can run the command in loop itself:

for i in `seq 1 20`; do ./getimages.sh $i rocky%20mountains ; done;

However, if you really do want to incorporate, a quick way is to move the main script code inside another function and write a for loop to invoke that function. Your bass script would then become:

#! /bin/bash

# function to create all dirs til file can be made
function mkdirs {
    file="$1"
    dir="/"

    # convert to full path
    if [ "${file##/*}" ]; then
        file="${PWD}/${file}"
    fi

    # dir name of following dir
    next="${file#/}"

    # while not filename
    while [ "${next//[^\/]/}" ]; do
        # create dir if doesn't exist
        [ -d "${dir}" ] || mkdir "${dir}"
        dir="${dir}/${next%%/*}"
        next="${next#*/}"
    done

    # last directory to make
    [ -d "${dir}" ] || mkdir "${dir}"
}

function getMyImages {
    # get optional 'o' flag, this will open the image after download
    getopts 'o' option
    [[ $option = 'o' ]] && shift

    # parse arguments
    count=${1}
    shift
    query="$@"
    [ -z "$query" ] && exit 1  # insufficient arguments

    # set user agent, customize this by visiting http://whatsmyuseragent.com/
    useragent='Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0'

    # construct google link
    link="www.google.com/search?q=${query}\&tbm=isch"

    # fetch link for download
    imagelink=$(wget -e robots=off --user-agent "$useragent" -qO - "$link" | sed 's/</\n</g' | grep '<a href.*\(png\|jpg\|jpeg\)' | sed 's/.*imgurl=\([^&]*\)\&.*/\1/' | head -n $count | tail -n1)
    imagelink="${imagelink%\%*}"

    # get file extention (.png, .jpg, .jpeg)
    ext=$(echo $imagelink | sed "s/.*\(\.[^\.]*\)$/\1/")

    # set default save location and file name change this!!
    dir="$PWD"
    file="$1_$count"

    # get optional second argument, which defines the file name or dir
    if [[ $# -eq 2 ]]; then
        if [ -d "$2" ]; then
        dir="$2"
        else
        file="${2}"
        mkdirs "${dir}"
        dir=""
        fi
    fi   

    # construct image link: add 'echo "${google_image}"'
    # after this line for debug output
    google_image="${dir}/${file}"

    # construct name, append number if file exists
    if [[ -e "${google_image}${ext}" ]] ; then
        i=0
        while [[ -e "${google_image}(${i})${ext}" ]] ; do
        ((i++))
        done
        google_image="${google_image}(${i})${ext}"
    else
        google_image="${google_image}${ext}"
    fi

    # get actual picture and store in google_image.$ext
    wget --max-redirect 0 -qO "${google_image}" "${imagelink}"

    # if 'o' flag supplied: open image
    [[ $option = "o" ]] && gnome-open "${google_image}"

    # successful execution, exit code 0
    #exit 0
}


for i in `seq 1 $1`; 
do 
    echo "Downloading image" $i
    getMyImages $i "$2"; 
done;

To download the first 10 images, simply invoke is as previously:

./getimages 10 rocky%20mountains
2
  • I didn't test the bash script, as your solution to run the command in loop works great. Could you modify the original bash script that I posted to name the downloaded files according to the search term? As of now the images are named "google image" with parenthetical numbers. Ideally I'd like the images to be named after the search term, followed by incremental numbers so they don't overwrite each other. – whitewings May 31 '15 at 13:27
  • 2
    @user8547 I have updated my answer. However, you should be able to do this yourself. – shivams May 31 '15 at 16:18

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.