Copy all files with a certain extension from all subdirectories

240,848

Solution 1

--parents is copying the directory structure, so you should get rid of that.

The way you've written this, the find executes, and the output is put onto the command line such that cp can't distinguish between the spaces separating the filenames, and the spaces within the filename. It's better to do something like

$ find . -name \*.xls -exec cp {} newDir \;

in which cp is executed for each filename that find finds, and passed the filename correctly. Here's more info on this technique.

Instead of all the above, you could use zsh and simply type

$ cp **/*.xls target_directory

zsh can expand wildcards to include subdirectories and makes this sort of thing very easy.

Solution 2

From all of the above, I came up with this version. This version also works for me in the mac recovery terminal.

find ./ -name '*.xsl' -exec cp -prv '{}' '/path/to/targetDir/' ';'

It will look in the current directory and recursively in all of the sub directories for files with the xsl extension. It will copy them all to the target directory.

cp flags are:

  • p - preserve attributes of the file
  • r - recursive
  • v - verbose (shows you whats being copied)

Solution 3

I had a similar problem. I solved it using:

find dir_name '*.mp3' -exec cp -vuni '{}' "../dest_dir" ";"

The '{}' and ";" executes the copy on each file.

Solution 4

I also had to do this myself. I did it via the --parents argument for cp:

find SOURCEPATH -name filename*.txt -exec cp --parents {} DESTPATH \;

Solution 5

find [SOURCEPATH] -type f -name '[PATTERN]' | 
    while read P; do cp --parents "$P" [DEST]; done

you may remove the --parents but there is a risk of collision if multiple files bear the same name.

Share:
240,848

Related videos on Youtube

Abdel
Author by

Abdel

My research is on the genetics of complex traits and population genetics. Sometimes I use Perl, R, or bash to program something, and usually when I get stuck, the friendly users of stackoverflow are of great help :-) #SOreadytohelp

Updated on July 08, 2022

Comments

  • Abdel
    Abdel almost 2 years

    Under unix, I want to copy all files with a certain extension (all excel files) from all subdirectories to another directory. I have the following command:

    cp --parents `find -name \*.xls*` /target_directory/
    

    The problems with this command are:

    • It copies the directory structure as well, and I only want the files (so all files should end up in /target_directory/)

    • It does not copy files with spaces in the filenames (which are quite a few)

    Any solutions for these problems?

    • fedorqui
      fedorqui over 11 years
      What about find... exec mv ?
    • jww
      jww almost 6 years
    • ingernet
      ingernet almost 4 years
      this question actually answered the question i came here to ask. thank you!
  • Abdel
    Abdel over 11 years
    Sorry for my bash illiteracy, but what do you mean by "bin"?
  • Brian Agnew
    Brian Agnew over 11 years
    Yes. 'bin it' means to throw it away. Now amended :-)
  • Abdel
    Abdel over 11 years
    Haha got it! Tnx! It doesn't quite work for me yet unfortunately... The "cp */.xls target_directory" for some reason does not copy all the files (it only looks 1 subdirectory deep, and does not copy files in subdirectories of subdirectories). The "find . -name *.xls* -exec cp ..." command gives me the message "find: missing argument to `-exec'"
  • pynexj
    pynexj over 11 years
    Bash 4.0+ and ksh93 also supports **. For bash, use shopt -s globstar to enable it. For ksh, it's set -G or set -o globstar.
  • Kevin Suttle
    Kevin Suttle almost 9 years
    How would you do this in bash 3.2?
  • Taywee
    Taywee almost 8 years
    That exec is technically less efficient than passing into xargs, which will do it all in as few cp calls as possible: find . -name '*.xls' -print0 | xargs -0 cp -t destdir
  • Brian Agnew
    Brian Agnew almost 8 years
    @Taywee - yes. I didn't want to confuse matters, however, and simply focus on the particular issue. A further efficiency measure is always good
  • Taywee
    Taywee almost 8 years
    @BrianAgnew Oh, I'm sure, just good to have extra information in the comments for wayward googlers.
  • Plummer
    Plummer over 7 years
    This is the same as what I had to do when SSH'd into Bluehost.
  • lal
    lal about 7 years
    Using this zsh cp variant for serching within a directory: cp -pPR **en.lproj/*.strings SignLocalization.
  • b005t3r
    b005t3r over 6 years
    It does NOT preserver subdirs.
  • TheWhitestOfFangs
    TheWhitestOfFangs over 5 years
    @BrianAgnew This copies the files indeed, however it does not retain the directory structure if used recursively. Is there a quick way of making it retain the directory tree from the source?
  • Datbates
    Datbates about 5 years
    Thanks! Wanted to grab all images and this expansion with a regex worked really nicely find -E source -iregex ".*\.(jpg|jpeg|tiff|png|mpeg|mp4|m4v|avi|mov|mts|m2ts|vob)" -exec cp {} destination \; (mac os)
  • Madivad
    Madivad almost 5 years
    @b005t3r that is by design, it is not supposed to. That was the whole intent of the OP's question. He wanted all files from subdirectories copied into one directory without subdirs
  • Matthew Dean
    Matthew Dean about 4 years
    Is there a way to modify this to preserve sub-directories?
  • Ivankovich
    Ivankovich almost 4 years
    note that the destination directory must already exist, otherwise this script will simply copy and rename the file to the directory name you supply.
  • drmercer
    drmercer almost 4 years
    @MatthewDean You can use the --parents flag to cp to accomplish that. Something like find ./ -name '*.xsl' -exec cp --parents {} targetDir/ ';'
  • Jordan McBain
    Jordan McBain over 2 years
    What do the braces do? and why the ';'