I have an issue in copying my file in my directories.

I have .txt and .jpeg files in a lot of directories, and I want to copy only the .txt files according to the directory. For example, I have this:




in my copy command I need only the .txt files from each directory

  • Where do you want to copy them to? – John May 22 '15 at 11:33
  • You mean cp direct/direct*/*.txt /destination or printf '%s\0' direct/direct*/*.txt | pax -rw0 /destination ? – Stéphane Chazelas May 22 '15 at 11:35
  • in another directory – toto May 22 '15 at 11:36
  • You might use find: find /path/to/direct -name "*.txt" -exec cp {} /destination \; – Lambert May 22 '15 at 11:47
  • @lambert I would not use \; but + in that command – Anthon May 22 '15 at 11:58

If you want to copy all the .txt files in a directory, use a wildcard pattern:

cp direct/direct1/*.txt target

This copies all the .txt files that are in the directory direct/direct1 to the directory target (which must already exist).

You can pass multiple patterns to copy files from multiple directories:

cp direct/direct1/*.txt direct/direct2/*.txt target

If you want to copy the .txt files from all the subdirectories of direct, you can use a wildcard for the directory as well:

cp direct/*/*.txt target

If you only want to copy from certain directories, you can use a wildcard pattern that matches only these directories. For example, if direct has four subdirectories foo, bar, baz and qux and you only want to copy files from bar and baz, you can use

cp direct/ba?/*.txt target

None of the examples so far copy files from direct itself, or from subsubdirectories of direct. If you want to copy the .txt files from direct, you need to include it in the list, e.g.

cp direct/*.txt direct/*/*.txt target

If you want to copy files from direct, all of its subdirectories, all of their subdirectories, and so on recursively, you can use the ** wildcard, if your shell supports it. It works out of the box in zsh, but in bash, you need to enable it first with shopt -s globstar.

cp direct/**/*.txt target

Note that all the files are copied into target itself, this does not reproduce the directory structure. If you want to reproduce the directory structure, you need a different tool, such as rsync (tutorial) or pax.

rsync -am --include='*.txt' --include='*/' --exclude='*' direct/ target/
cd direct && pax -rw -pe -s'/\.txt$/&/' -s'/.*//' . target/
| improve this answer | |

You can use find to only select the `.txt files from under some directory:

find direct/direct? -name "*.txt"

this would print out all the files, so you can check you got what you wanted, and not too much is going to be selected. The *.txt has to be quoted, otherwise the shell will try expand this to .txt files in the current directory.

As for the copying, you want to do (most often) one of two things: preserve the path under direct to the .txt file or not. To preserve it use:

find direct/direct? -name "*.txt" -print0 | cpio -pdmv0 target_directory

to copy all the .txt files into one target directory use something similar to what @lambert suggested:

find direct/direct? -name "*.txt" -exec cp {} target_directory +

(using + instead of \; is more efficient as multiple filenames are passed to a single cp when + is used instead of invoking a cp for every single file when using \;)

For the second command -print0 is not necessary to handle paths with special characters the filename that replace {} are properly separated by the way cp is invoked.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.