102

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.

Oliver Salzburg
  • 89,072
  • 65
  • 269
  • 311

8 Answers8

120

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.)
cedric
  • 103
11
cd /source/path
find -type f -name \*.txt -exec install -D {} /dest/path/{} \;
sborsky
  • 1,125
8

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
icyerasor
  • 688
5

Another approach

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

Marc
  • 151
4

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: http://www.gnu.org/software/findutils/manual/html_mono/find.html#Copying-A-Subset-of-Files

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

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

k-h
  • 167
Dennis
  • 353
3

I was trying to do the same thing on macOS, but none of the options really worked for me. Until i discovered ditto.

I had to copy many .wav files, and have it skip Video files... So here is what I came up with:

find . -type f -iname "*.wav" -ls -exec ditto {} /destination/folder/{} \;

  • find . - Runs find in current folder. make sure you cd /source/folder before you start

  • -type f - Specifies to only look for files

  • -iname "*.wav" - This tells it to look for case insensitive *.wav
  • -ls - This shows you the file that it is working on. Otherwase it shows nothing.
  • -exec ditto {} /destination/folder/{} \; - Does all the work of copying and creating the files with the same directory tree.
1

Navigate to directory:

find . -regex '<regexp_to_get_directories_and_files_you_want>' | xargs -i cp -r --parents {} path/to/destination

It s a bit more straight forward and mighty, if you manage regular expressions.

-1

Navigate to directory:

cp '*.css' /path/to/destination

You'll have to navigate to each folder in the directory, but this is better than most of the options I've seen so far.

Gareth
  • 19,080