Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

At the Linux command line, I'd like to copy a (very large) set of .txt files from one directory (and its subdirectories) to another.

I need the directory structure to stay intact, and I need to ignore files except those ending in .txt.

share|improve this question
Having cp and find as tags in your question, does it mean that you're tied to these options? Since your dataset is very large, it makes sense to assume the copying process can get interrupted for some reasons and you'll have to restart it. I'm not sure the find/cp approach will be able to resume the transfer and copy only the missing part. If you aren't tied to find/cp, you could consider rsync, which is smarter. Its --exclude option will alow you to skip .txt files. – vtest Jun 21 '11 at 8:42
Fair call - rsync probably is the better option. Not tied to find/cp. (I used them anyway - rsync wasn't installed on the remote machine, it was a live web server & I wanted to leave as small of a footprint as possible) – unclaimedbaggage Jun 22 '11 at 0:08
up vote 65 down vote accepted

You can use find and cpio to do this

cd /top/level/to/copy
find . -name '*.txt' | cpio -pdm /path/to/destdir

(-updm for overwrite destination content.)
share|improve this answer
cd /source/path
find -type f -name \*.txt -exec install -D {} /dest/path/{} \;
share|improve this answer

how about you first copy it over with

cp -r /old/folder /new/folder

then go to the new folder and run

find . -type f ! -iname "*.txt" -delete

or just

cp -r /old/folder /new/folder && find . -type f ! -iname "*.txt" -delete

Edit: ok you want one command which filters (I have not tested this because my system doesn't have the cpio command!). Here is where I found it:

find . -name "*.txt" |
     cpio -pmd0 /dest-dir

Please test this first, because I haven't tried it yet. If someone would verify, that would be great.

share|improve this answer
nods Cheers - this would work, but without filtering to .txt I'm looking at a few million files (coming out at a few hundred GB). If need be I may have to, but I'd love to filter while copying if possible – unclaimedbaggage Jun 21 '11 at 5:09
Cheers, edited version works if I remove the '0' from -pmd0 – unclaimedbaggage Jun 22 '11 at 0:06
You should keep the 0 in -pmd0 and add -print0 to the end of the find command (just before the |). – G-Man Sep 11 '14 at 21:51

Easiest way that worked for me:

cp --parents -R jobs/**/*.xml ./backup/

one catch is you have to navigate to the "desired" directory before so the "parent path" is correct.

Also make sure that you enabled recursive globs in bash:

shopt -s globstar
share|improve this answer

Another approach

find . -name '*.txt' -exec rsync -R {} path/to/dext \;

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .