-printf '%f\n'
is a GNU extension that prints the trailing portion of the current file path followed by a newline character. If the file path is /test/downloads/foo
, it prints foo\n
.
xargs
takes that output. Here foo
contains none of the characters treated specially by xargs
with -I{}
(quoting characters, newlines (the only delimiter with -I
) and leading whitespace, an EOF character with some).
So {}
is replaced with foo
in the arguments passed to cp
. So cp
ends up being called with cp
, -R
, foo
, /test/uploads/
as arguments.
So cp
will look for foo
in the current working directory, not in /test/downloads
.
If the file had been called /test/downloads/-t..
, the command would have been
cp -R -t.. /test/uploads/
Which tells cp
to copy /test/uploads/
to the parent directory of the current working directory.
If the file name had been /test/downloads/ 'blah'<newline>"blah"
, cp
would have been called twice as cp -R blah /test/uploads/
.
So you have two problems:
- With
%f
, you're stripping the leading directory components to the file
- You're using
xargs
which cannot be used reliably on the output of find
(other than with the non-standard -r
and -0
options to process NUL-delimited records).
One could also add that you're calling cp
for each directory even though cp
is well capable of copying more than one file at a time.
Here, standardly, that should be:
find /test/downloads/. ! -name . -prune -type d -mtime -1 -exec sh -c '
exec cp -R "$@" /test/uploads/' sh {} +
Which with GNU implementations of those utilities (as found by default in your Debian system) can be simplified to:
find /test/downloads/ -mindepth 1 -maxdepth 1 -type d -mtime -1 \
-exec cp -Rt /test/uploads/ {} +
find ... | xargs -I xx echo xx /test/uploads/
. In casexx
is a relative path it may have to be adjusted or prefixed. – Andre Wildberg Jan 04 '21 at 23:53%p
rather than%f
– steeldriver Jan 04 '21 at 23:54