cp recursive with specific file extension
I am trying to copy all .odt
files including those in subdirectories.
cp -r ~/Documents/* ~/copies # works as expected
cp -r ~/Documents/*.odt ~/copies # does not work as expected
The first line will copy all files and in all subdirectories but the second will copy only the .odt
files in ~/Documents
and none of the files in the subdirectories.
You can either let the (bash) shell do the recursion instead:
shopt -s globstar
cp -nt ~/copies/ ~/Documents/**/*.odt
or use the find
command
find ~/Documents -name '*.odt' -exec cp -nt ~/copies/ {} +
The former may exceed the system's ARG_MAX
limits if the number if files is very large, whereas the latter will break the command up to stay within ARG_MAX
.
I added the -n
option to prevent "clobbering" files with the same name.
If you wish to replicate the directory structure (more like what cp -r
does as suggested by steeldriver) but only populate it with the .odt
files, you can do it with rsync
, where -f
is the 'filter' option. The other options are more straight-forward. You find all the options in man rsync
.
rsync -nvr -f '+ *.odt' -f '+ **/' -f '- *' --prune-empty-dirs ~/Documents/ ~/copies/
It is a good idea to use the 'dry run' option -n
and the verbose option -v
in order to see what will be done before running the real command (when n
is removed from the command line).