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 whichfind
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 forcp
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 \;
executessleep 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
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' "{}" \;