Say I want to copy a folder with 1000 files and lots of subfolders, and I need to do this on Mac terminal because it is a part of streamlined process programmed on bash script. Thus I can not just open Finder, select all and copy from there. I can do this very easily with
cp -r source_folder target_path
However, what if I want to exclude some files/subdirectories in this code?
So far, I have put the following requirements:
- There are lots of files to copy, like 1000.
- There are still lots of files to exclude, like 50.
- It must be programmed in bash so no Finder / manual work. One command done
Unfortunately, cp does not offer the function to exclude certain files. Here we need to use rsync.
According to the manual of rsync, it has the following features
- It basically copies, like cp, or rcp (remote copy)
- It has a lot more options than the basic copy.
- It is much faster.
Thus it is good to use rsync. Now let’s go back to the topic: excluding some files or subdirectories during copy. We need to use –exclude option.
We can either put a specific file name or something more general with the asterisk. For example, this one below exclude all hidden files or directories from the copying.
rsync -r source_folder target_path --exclude='.*'
Also, we should notice that, just like cp, copying folders using rsync should put -r. If we only want to exclude a folder called bin, we then should
rsync -r source_folder target_path --exclude='bin'
Excluding multiple elements
If we have more than one element to exclude, we just add more –exclude.
rsync -r source_folder target_path --exclude='bin' --exclude='scripts'
Excluding only hidden folders?
Now that we successfully excluded all hidden files or certain files. What if I still want the files but not the folders? In this case, we use a slash ‘/’ to indicate folders. Like the command below, .*/ means all hidden folders.
rsync -r source_folder target_path --exclude='.*/'
Include back certain files/folders
Say I want to exclude all hidden files but not the hidden folders. However, .*/ means only folders; .* means both files and folders. I did not find anyway to mean only files. Thus, we should use the –include option to include the folders first and then exclude everything, like the command below. To better understand this, according to the manual of rsync, –include tells rsync “not to exclude a pattern”.
rsync -r source_folder target_path --include='.*/' --exclude='.*'