touch source
$ echo dest.{000000..999999} | tr ' ' '\n' | while read dest ; do echo cp -v source $dest ; done
cp -v source dest.000000
cp -v source dest.000001
cp -v source dest.000002
cp -v source dest.000003
cp -v source dest.000004
cp -v source dest.000005
cp -v source dest.000006
cp -v source dest.000007
cp -v source dest.000008
cp -v source dest.000009
...
Well, this is gonna take forever, mainly because each copy invokes a new cp
process.
Let's try with xargs:
$ echo dest.{000000..999999} | xargs -n 1000 cp source
cp: target 'dest.000999' is not a directory
Yeah, right, when giving multiple arguments, cp
assumes that n-1
arguments are source files, and the nth
argument is a destination directory.
I need a command that works differently:
mycp source dest1 dest2 dest3 ...
How could I achieve this, without invoking a new process for each copy?
CodePudding user response:
Replace
mycp source dest1 dest2 dest3 ...
with
cat source | tee dest1 dest2 dest3 ...
or
tee dest1 dest2 dest3 ... < source
or add this function to your ~/.bashrc
mycp() { source="$1"; shift; tee "${@}" < "$1"; }
source it and then use
mycp source dest1 dest2 dest3 ...
CodePudding user response:
(based on the suggestion by Cyrus)
This works:
function multi-cp () {
local source="$1"
shift
tee "${@}" < "$source" > /dev/null
}
echo dest.{000000..999999} | xargs -n 1000 | while read -r destinations ; do
multi-cp source $destinations
done
We use while
because xargs
can not call functions (there are ways around this, but they have other problems). We still use xargs
to split the arguments in manageable chunks.
This assumes that the arguments have no spaces (which is the case, since we are in control).