-v
is not specified by POSIX. This means each cp
implementation may handle it differently (or not at all). Where your cp
says « foo »
my says 'foo'
. It's possible to craft a command that would transform your undesired output into the desired one, still I'd like to present a solution independent from cp
implementation.
After /src/*
in your command expands, cp
copies the resulting entries one by one. This means you can turn cp -n /src/* /dest/
into
for file in /src/*; do cp -n "$file" /dest/; done
Now it's easy to do something with $file
. This will generate the output you want:
for path in /src/*; do
file="${path##*/}"
dst="/dest/$file"
[ ! -e "$dst" ] && cp "$path" "$dst" && printf '%s\n' "${file%.*}"
done
(To redirect to copy_result.txt
use done > copy_result.txt
instead of just done
).
Note if you used cp -r -v
and at least one of the operands from the expansion of /src/*
was a directory, cp
would copy and print its contents, while the above code (after we add -r
) would copy as much but print only the directory itself. -r
may not be the only option that would introduce discrepancy.
So while the approach should be independent from cp
implementation, it relies on some option(s) not being used. Another disadvantage is the code runs a separate cp
process for every object in /src/
, this is far from optimal.
There's also a race condition: if the $dst
file appears between [
and cp
, cp
will do its job. You can use cp -n
to avoid overwriting, but printf
will still report the file.
2What about files
/src/with spaces.txt
? – Kamil Maciorowski – 2019-04-04T20:17:46.727@Davey The command is working perfectly thank you for your response – Angelika – 2019-04-05T11:46:21.120
@Davey When running the bash, it says that : bash: /bin/cp: Argument list too long – Angelika – 2019-04-05T15:10:20.963
Did you make sure to include the first '|'? What OS are you on? – Davey – 2019-04-05T15:41:59.150
@Davey yes I included '|' ,It's CentOS – Angelika – 2019-04-08T08:06:02.533
@Angelika You got
argument list too long
because/src/*
expands to too many entries. Such pattern infor
loop (like in my answer) is immune to the issue: the long list exists internally in the shell only, no external tool gets a list that is too long. A loop is a common way to deal with the issue; another one isfind -exec
orfind | xargs
. – Kamil Maciorowski – 2019-04-08T08:23:02.033