Copy files from one folder to another but have an interval between each file

Single command solutions

Among many options, including loops that make use of cp and sleep, we could opt for find with two -exec flags to run those exact commands.

find ~/dir_1/ -type f -maxdepth 1  -exec cp {} ~/dir_2 \;  -exec sleep 1   \;

Here the options are:

  • ~/dir_1 , the origin directory, through which find works.
  • -type f get only files
  • -maxdepth 1 descend down 1 level maximum in the directory tree; prevents descending into subdirectories
  • -exec cp {} ~/dir_2 \; copy the currently processed file designated by {} parameter to ~/dir_2. The \; designates for cp to process single file at a time instead of tacking as many files as possible into {}. The backslash in \; is necessary to prevent shell from misinterpreting that as command terminator.
  • exec sleep 1 \; executes sleep 1 per each current file.

If you have a list of files in a file, you can do:

xargs -I % --arg-file=input.txt sh -c 'cp % ~/dir_2/ ;sleep 1'

Options here are:

  • -I % designates the symbol which refers to file within the command
  • --arg-file=input.txt read arguments to command from specific file
  • sh -c 'cp % ~/dir_2/ ;sleep 1' execute /bin/sh with provided commands by -c '...' flag; % will be substituted with filename.

Loop solutions

You could use a for loop for instance

for f in "/path/to/folder_1"/*; do
    cp "$f"  "/path/to/folder_2/"
    sleep 1
done

For clarity, this is formatted on multiple lines, but this works as a single line just as well. You could also turn this into a function:

delaycp(){
    for f in "$1"/*; do
        cp "$f"  "$2"/
        sleep 1
    done
}

And use it as

delaycp "/path/to/folder1" "/path/to/folder2"

Alternatively, if you want to copy only certain files, not everyting that * glob captures in the directory, you could always make use of pathname expansion, something like file{1..25}, or have an input text file, something like this input.txt:

/path/to/folder_1/file1
/path/to/folder_1/file2
/path/to/folder_1/file3

And from there make use of while IFS= read -r line structure to read the file:

while IFS= read -r line || [ -n "$line" ]; do
    cp "$line" "/path/to/folder_2/${line##*/}"
    sleep 1
done < input.txt

With parallel

Here’s a parallel Install parallel solution, give the arguments to parallel with ::: exactly like with cp or use a file list:

parallel -j1 'cp {} /path/to/dir2/;sleep 1' ::: /path/to/dir1/* # or
parallel -j1 'cp {} /path/to/dir2/;sleep 1' :::: /path/to/file_list.txt

The -j option tells parallel to run only 1 job at once rather than running jobs in parallel, the single quotes simply contain the script where {} is replaced with the currently processed file and ::: or :::: introduce the argument list or file(s) respectively. See man parallel for much more.

With find -exec

find provides a convenient way of running commands on the findings, e.g. to copy every .log file in and under the current directory do:

find -name "*.log" -exec sh -c 'cp "$0" /path/to/dir2/;sleep 1' "{}" \;