As you might already know, ‘cp’ is the command line program in Linux to copy files and directories. The simple and most common use of ‘cp’ is as follows:
$ cp file1 file2 file3... fileN target_folder/
Note that the above command works for files as well as ’empty’ folders. It does not work for folders that have some content, either files or subfolders.
Recursively Copy Files in Linux
To copy such folders, we can specify the '-r'
(recursive) flag.
$ cp -r folder1/ folder2/ file1 file2 target_folder/
Recursive copying implies that the whole folder structure beneath a folder, i.e., subfolders and files in them, subfolders inside the subfolders and the files in them, and so on, is copied.
This copies all the files, and there is no way within the ‘cp’ command to exclude some of the files based on certain parameters.
For example, users might want to copy all the files recursively, except MP3 (audio) files in the subfolders all the way down in the hierarchy.
Find All Files Except Certain File Extension
To achieve this, we use the find command, which is a command tool simply used to search for files and folders in Linux based on the parameters of the file or folder: filename, extension, size, etc.
Similarly, there are ways to search files by specifying which files should be excluded in the find command.
The syntax to locate files of a specific extension using find is:
$ find <folder_to_search> -name '*.<extension>'
For example, to locate all MP3 files recursively in the current folder:
$ find . -name "*.mp3"
Now, to find all the files in the folders and subfolders, except MP3 files, use the ‘negation’ operator of find:
$ find . ! -name "*.mp3"
We can see that now everything except the MP3 files is displayed. However, we want only to display the files, because this output will later be input to ‘cp’. Right now, it is displaying both files and folders (Eg. ‘temp1/’), which will lead to repetitive copies of the same files.
To remove the folders from the output, simply use the argument '-type f'
. Here 'f'
stands for a file.
$ find . ! -name '*.mp3' -type f
We thus now have just the files obtained recursively inside the folder ‘test’. Now we can proceed to pipe this output to the ‘cp’ command.
Exclude File Extension While Copying Recursively
To do this, we use the ‘xargs’ command to make ‘cp’ consider the output of ‘find’ as its arguments. Also, we use the '-t'
flag to specify the target directory, without which the program considers the output of ‘find’ as the target directory.
$ find <folder_to_search> ! -name '*.<extension>' -type f | xargs cp -t <target_directory>
Actual command.
$ find . ! -name '*.mp3' -type f | xargs cp -t Misc/
Thus, all the files found recursively, except the “.mp3”
files have been copied to folder “Misc”.
Conclusion
In this article, we learned how to copy files recursively in Linux while excluding files of a certain extension. Also, take a look at how to recursively copy files of a specific extension.
If you have any questions or feedback, let us know in the comments below.
And what one should do if they’re more than 1 file type to exclude? E.g. not only mp3 files but, say, flac, wav, ra, ogg. ape, and wma files as well?
@Andrew,
You need to mention each file type with
-name
option with find command to exclude multiple file types as shown in the article…