Copy .txt files in a certain directory
Solution 1
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/
Solution 2
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.
Related videos on Youtube
toto
Updated on September 18, 2022Comments
-
toto almost 2 years
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:direct/direct1 direct/direct2 direct1: file.txt file2.txt file.jpeg file2.jpeg direct2: file3.txt file4.txt file3.jpeg file4.jpeg
in my copy command I need only the
.txt
files from each directory-
John about 9 yearsWhere do you want to copy them to?
-
Stéphane Chazelas about 9 yearsYou mean
cp direct/direct*/*.txt /destination
orprintf '%s\0' direct/direct*/*.txt | pax -rw0 /destination
? -
toto about 9 yearsin another directory
-
Lambert about 9 yearsYou might use find:
find /path/to/direct -name "*.txt" -exec cp {} /destination
\; -
Anthon about 9 years@lambert I would not use
\;
but+
in that command -
Lambert about 9 years@Anthon, If you use
+
instead of\;
you are not able to specify a target directory. Thecp
command will not take multiple sources. Please correct me if I am wrong -
Anthon about 9 years@Lambert I correct you:
mkdir tmp; cd tmp; touch a b c d; mkdir t; cp a b c d t; ls t;
showsa b c d
-
Lambert about 9 years@Anthon, thanks, I tested the suggested
+
before and it does not work in my case:mkdir s; find t/ -exec cp {} s +
gives me:find: missing argument to '-exec'
-
Lambert about 9 yearsIn that case I think that
find /path/to/direct -name "*.txt" | xargs | xargs -I{} cp {} /destination
works better than using the+
option. BTW, I found a confirmation to your correction in the manual of cp:Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
I completely overlooked that.
-