If I wanted to copy all *.so files from src to dst I'd do:
cp src/*.so dst However, I want to copy all *.so files from src and it's subdirs into dst. Any clues?
If I wanted to copy all *.so files from src to dst I'd do:
cp src/*.so dst However, I want to copy all *.so files from src and it's subdirs into dst. Any clues?
Try:
find src/ -type f | grep -i so$ | xargs -i cp {} dst find can do pattern matching and execute commands. There's no need to pipe its output: find src/ -type f -name '*.so' -exec cp '{}' dst/ ';' grep far outweigh the simple shell patterns used in the -name parameter to find. xargs is also far more powerful than the -exec parameter to find. If you're using Bash, you can turn on the globstar shell option to match files and directories recursively:
shopt -s globstar cp src/**/*.so dst If you need to find files whose names begin with ., and/or files in and under directories whose names begin with ., set the dotglob option also (e.g., with shopt -s dotglob). You can set them both in one command:
shopt -s globstar dotglob I tried the command suggested by Mike:
find src/ -type f | grep -i so$ | xargs -i cp {} dst but it ended up with dumping all the files into directory dst with their relative paths lost.
To keep the relative paths the command needs to be modified to this:
find src/ -type f | grep -i so$ | xargs -i cp {} dst/{} dst. In case that's not so, use cp --parents. Also, be sure to quote the filenames. Thus: ... | xargs -i cp --parents "{}" dst (note that the last argument to cp is now "just" the destination directory). The command can be made even shorter (and probably faster) using the -t flag: ... | xargs cp --parents -t dst. ... | xargs cp {} --parents -t dst. --parents isn't available. I used ditto in its place: stackoverflow.com/questions/11246070/cp-parents-option-on-mac Another way of doing this is like this:
find src/ -type f -name "*.so" -exec cp {} dst/ \; cp processes: ... -exec cp -t dst/ {} +. -exec with ;, {} is replaced by one path at a time. You get a separate cp for every file. With + syntax find replaces {} with multiple results (up to a system-defined limit of command line length; restriction: {} must be the last thing before +, hence cp -t). Creating and terminating a process is relatively costly thing. For this reason it's good to use + whenever you expect lots of results. In this case copying lots of files might take a lot of time anyway so the difference may pass unnoticed; nevertheless it's a good practice. The grep can be replaced by using find's -name:
find src/ -type f -name "*.so" | xargs -i cp {} dst/{} For me,
shopt -s globstar cp src/**/*.so dst does not copy .so files directly in src. This does:
shopt -s globstar cp src/**/*.so dst cp src/*.so dst or this
shopt -s globstar cp src/{**/*,*}.so dst But it solves the problem of copying things directly into dst, without preserving paths.
For copying from an absolute path, I had to add a sed command.
Also, as --parent did not work properly (cp: with --parents, the destination must be a directory), I had to create the folders first.
find /root/src/ -type f \ | grep -i so$ \ | sed "s|^/root/src/||" \ | sed "s|/\([^/]*\)so$||" \ | xargs -i mkdir --parents /root/dst/{} find /root/src/ -type f \ | grep -i so$ \ | sed "s|^/root/src/||" \ | xargs -i cp /root/src/{} /root/dst/{}