linuxbashshell

I am creating a bash script to organize files in my Downloads folder, how can I iterate using "For" loop


Here is my bash script:

#!/bin/bash


image=$(find ~/Downloads -type f \( -iname "*.jpg" -o -iname "*.png" \) ) 

# Print found images to debug
echo "Found images: $image"

if [ ! -d ~/Downloads/images ]; then
    mkdir -p ~/Downloads/images
    for i in $image
        do
        mv $image ~/Downloads/images
        done
else
    for i in $image
        do
        mv $image ~/Downloads/images
        done
fi

When I execute the script, it does not iterate and starts throwing error. Can someone help me?

Tried using awk -F/ '{print $NF}' in find, but it caused issues while moving the files.

The error message when running on some sample files:

mv: '/home/ermac/Downloads/images/car.jpg' and '/home/ermac/Downloads/images/car.jpg' are the same file 
mv: '/home/ermac/Downloads/images/itachi.jpg' and '/home/ermac/Downloads/images/itachi.jpg' are the same file 
mv: cannot stat '/home/ermac/Downloads/spirited': No such file or directory mv: cannot stat 'away.jpg': No such file or directory

Updated code:

image=$(find ~/Downloads -type f \( -iname "*.jpg" -o -iname "*.png" \) ) 

# Print found images to debug
echo "Found images: $image"

mkdir -p ~/Downloads/images

    for i in $image
        do
        mv $i ~/Downloads/images # Move current image
    done

output:

Found images: /home/ermac/Downloads/car.jpg
/home/ermac/Downloads/itachi.jpg
/home/ermac/Downloads/spirited away.jpg
mv: cannot stat '/home/ermac/Downloads/spirited': No such file or directory

Solution

  • Your error is that you are trying to loop through $image, which contains multiple images. Hence, in each iteration of the loop, you should pass the current element i instead of all the files in $image. See the below code, which is also cleaned up a bit (see this):

    #!/bin/bash
    
    
    image=$(find ~/Downloads -type f \( -iname "*.jpg" -o -iname "*.png" \) ) 
    
    # Print found images to debug
    echo "Found images: $image"
    
    mkdir -p ~/Downloads/images
    for i in "$image"
        do
        mv $i ~/Downloads/images
        done
    

    The code however is clunky and breaks if there is a space in the filename when attempting to loop through "$image". If the debug message is not necessary, the script can be instead written as:

    #!/bin/bash
    
    mkdir -p ~/Downloads/images
    find ~/Downloads -type f \( -iname "*.jpg" -o -iname "*.png" \) -exec mv {} ~/Downloads/images \;