Recursively copy files from one directory to another

65,568

Solution 1

Use:

find /media/kalenpw/MyBook/Music/ -name '*.mp3' -exec cp {} /media/kalenpw/HDD/Music \;

The reason for your command not working is that names containing wildcards (*.mp3) are expanded before the command is run, so if you had three files (01.mp3, 02.mp3, 03.mp3) your effective command was:

cp -R /media/kalenpw/MyBook/Music/01.mp3 /media/kalenpw/MyBook/Music/02.mp3 /media/kalenpw/MyBook/Music/03.mp3 /media/kalenpw/HDD/Music

As you can see -R has no effect in this case.

Solution 2

You have specifically mentioned the files(s)/directory(ies) to be copied as using *.mp3 i.e. any file/directory name ending in .mp3.

So any file ending in .mp3 in /media/kalenpw/MyBook/Music/ directory and similarly, any directory ending in .mp3 in /media/kalenpw/MyBook/Music/ will be copied, recursively. If there is no such matched file/directory, nothing will be copied.

Now to copy all .mp3 files from /media/kalenpw/MyBook/Music/ recursivley to directory /media/kalenpw/HDD/Music/:

  • Using bash:

    shopt -s globstar
    cp -at /media/kalenpw/HDD/Music /media/kalenpw/MyBook/Music/**/*.mp3
    
  • Using find:

    find /media/kalenpw/MyBook/Music -type f -name '*.mp3' -exec cp -at /media/kalenpw/HDD/Music {} +
    

Solution 3

The simplest way to do this would be to use a copy command with no wildcards and only directory names:

cd /media/kalenpw/HDD
cp -r /media/kalenpw/MyBook/Music .

If the current directory didn't already have a directory named Music, this would create a new Music directory in the current directory. If you already have a directory named Music, It would copy the contents of it to the existing Music directory. This, of course, would get all the files, not just the .mp3 files, so it might not give you the flexibility you need.

Solution 4

Suppose that you have a bunch of .docx, .mp3, .txt and .xlsx files stored in this directory structure:

/files/
/files/dir1/
/files/dir1/dir11/
/files/dir1/dir12/
/files/dir1/dir13/
/files/dir2/
/files/dir3/
/files/dir3/dir31/
/files/dir3/dir32/
/files/dir4/
/files/dir5/
/files/dir51/
/files/dir52/
/files/dir53/
/files/dir54/

...and you want to recurse into all such directories in order to copy all found .mp3 files to /home/me/music/ but you do not want to preserve such directory tree in the destination (i.e. you want all found .mp3 files to be copied to /home/me/music/ instead of copied to respective directories such as /home/me/music/dir1/, /home/me/music/dir1/dir11/ et cetera).

In such case, at the shell terminal (bash) first run this command in order to access the root of your file search:

cd /files

...and then run this command:

for i in `find . -iname '*.mp3'`; do cp $i /home/me/music/; done

In case you do want to preserve the source's directory tree in the destination, run this command instead (after running cd /files):

find . -iname '*.mp3' | cpio -pdm /home/me/music/

On the above commands, the search is case-insensitive (i.e. matches .mp3, .MP3, .mP3 and .Mp3). Use -name instead of -iname if you want the search to be case-sensitive (e.g. using -name for the .mp3 string of characters will match files ending with .mp3 but not those ending with .MP3, .mP3 nor .Mp3).

It's also important to point out that, in the case of the command that preserves the source directory tree/structure, those folders whose content doesn't match the search criteria won't be copied to the destination. Hence, if e.g. no .mp3 file is found in /files/dir5/, then no /home/me/music/dir5 directory will be created, but if at least one .mp3 file is found in /files/dir5/, then /home/me/music/dir5 will be created so such .mp3 file(s) can be stored inside of it.

Solution 5

You can also use cpr:

$ cd /media/kalenpw/HDD/Music
$ cpr -p '/\.mp3$/' '/media/kalenpw/MyBook/Music/'

Note that without -p cpr will preserve complete directory paths on copied filenames.
-r can be used (instead of -p) to preserve the path under '/media.../Music/'.
Also cpr will take care that no file is overwritten, appending a number starting at '0001' to any repeated filename copied.

Share:
65,568

Related videos on Youtube

kalenpw
Author by

kalenpw

Updated on September 18, 2022

Comments

  • kalenpw
    kalenpw over 1 year

    I have all my music in a folder /media/kalenpw/MyBook/Music/ABunchOfOtherFoldersWithFilesInside. I want to copy all of the mp3s to /media/kalenpw/HDD/Music so I used:

    cp -R /media/kalenpw/MyBook/Music/*.mp3 /media/kalenpw/HDD/Music
    

    however this only copied the mp3s in the root music folder and did not open any of the artist subdirectories and copy those files.

    I was under the impression -R would recursively copy all the files. How can I achieve said goal?

  • Olathe
    Olathe almost 8 years
    I recommend -iname instead of -name in case any files end in .MP3.
  • kalenpw
    kalenpw almost 8 years
    Thank you this worked. Or at least is in the process of working.
  • kalenpw
    kalenpw almost 8 years
    Thanks, techraf answered first so I accepted their answer, however.
  • Gautam Sreekumar
    Gautam Sreekumar about 4 years
    For the case where you want to preserve the directory structure, run this command from the source directory. If you run find /source/dir -iname '*.mp3' | cpio -pdm /home/me/music/, it will create /home/me/music/source/dir and the files would be copied to this new location.
  • Yuri Sucupira
    Yuri Sucupira over 3 years
    @GautamSreekumar The command find /source/dir -iname '*.mp3' | cpio -pdm /home/me/music/ creates a copy of the (preserved) directory sctructure in /home/me/music/source/dir instead of in /home/me/music. In order to prevent this from happening, you need to use find . instead of find /source/dir.