Script not copying over new files

I am writing a script that copies over any newer files to a destination. Here is my script:


#!/bin/bash

# Usage: ./copy_folders.sh /path/to/source1 /path/to/source2 ... /path/to/destination

# Ensure at least two arguments (at least one source and one destination)
if [ "$#" -lt 2 ]; then
    echo "Usage: $0 /path/to/source1 [/path/to/source2 ...] /path/to/destination"
    exit 1
fi

# Last argument is the destination
DESTINATION="${!#}"

# Create destination directory if it doesn't exist
mkdir -p "$DESTINATION"

# Loop over all arguments except the last one (destination)
for ((i=1; i<$#; i++)); do
    SOURCE="${!i}"
    
    # Check if source directory exists
    if [ ! -d "$SOURCE" ]; then
        echo "Warning: Source directory does not exist: $SOURCE"
        continue
    fi

    echo "Copying from $SOURCE to $DESTINATION"
    rsync -av --update "$SOURCE"/ "$DESTINATION"/
done

echo "All copies completed."

To confirm it worked, I look at a recently modified doc on my source side, and compare to the destination. The file on the destination side was NOT updated. I am comparing the Date Modified value shown to me in Nemo.

Hello and welcome!

What’s the output of rsync? And what’s the return value of rsync? You may add something like echo "rsync exit value: $?" right after calling rsync:

(...)
    rsync -av --update "$SOURCE"/ "$DESTINATION"/
    echo "rsync exit value: $?"
done

echo "All copies completed."

You can look up exit values of rsync on the man-page.

Are you using rsync as snap? Which folders do you use as source and destination?

You have added a trailing slash to the source, which changes the behaviour of rsync. From man rsync:

A trailing slash on the source changes this behavior to avoid creating an additional directory level at the destination. You can think of a trailing / on a source as meaning “copy the contents of this directory” as opposed to “copy the directory by name”.

This may be what you intended, but it is a “gotcha” with rsync.

Whilst you are debugging this, you might want to add the --itemize-changes and --stats options, and redirect your output to a log file.

Suggest that you try GUI grsync … and enable “dry run” option to see what is going on. You will see errors.

1 Like

This may save you the trouble of writing a script:

The cp command has tne option to only copy new files without updating existing ones.

use the -n option for this (optionally with other options)

Example: cp -rnp will recursively copy only files which don’t exist on the destination, without updating existing files, and preserve permissions. If you want to also update existing files, use the u option instead of n.

Note: Newer versions of cp deprecates the n option, and replaces it by --update=none

The exit code is 0.
I am not using it as snap.
Destination: mounted SSD, Source: Local folder