Skip to content

How to copy (or cp) files recursively with exclusions in Linux system

Problem

How to copy or cp files from a source to a destination recursively with some exclusions in a Linux operating system?

For example, I have a directory named A as follows:

➜ tree A
A
├── DEPENDENCIES
├── a.log
├── b.log
├── c.log
└── maven
└── org.apache.httpcomponents
└── httpclient
├── pom.properties
└── pom.xml
3 directories, 6 files

Now, I want to copy directory A to directory B recursively, but I don’t want to copy the log files to B.

Environment

  • Linux or MacOS

Solution

We can use rsync to resolve this problem:

rsync
rsync -avr --exclude='*.log' A/* B

After running the above command, let’s check the destination directory B:

B
├── DEPENDENCIES
└── maven
└── org.apache.httpcomponents
└── httpclient
├── pom.properties
└── pom.xml
3 directories, 3 files

It works!

How it works?

The rsync command can not only sync with a remote host’s directory but also sync with a local directory.

Let’s check the three options used in the above command:

Terminal window
-v, --verbose increase verbosity
-a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)
This is equivalent to -rlptgoD. It is a quick way of saying you want recursion and want to preserve almost everything (with -H being a notable omission).
-r, --recursive recurse into directories

The --exclude option can be used with patterns:

Terminal window
--exclude=PATTERN
This option is a simplified form of the --filter option that defaults to an exclude rule and does not allow the full rule-parsing syntax of normal filter rules.

Aside from --exclude, you can also use --exclude-from, --include, and --include-from:

Terminal window
--exclude-from=FILE
This option is related to the --exclude option, but it specifies a FILE that contains exclude patterns (one per line). Blank lines in the file and lines starting with ';' or '#' are ignored. If FILE is -, the list will be read from standard input.
--include=PATTERN
This option is a simplified form of the --filter option that defaults to an include rule and does not allow the full rule-parsing syntax of normal filter rules.
See the FILTER RULES section for detailed information on this option.
--include-from=FILE
This option is related to the --include option, but it specifies a FILE that contains include patterns (one per line). Blank lines in the file and lines starting with ';' or '#' are ignored. If FILE is -, the list will be read from standard input.

For example, if you want to exclude some types of files, just create a file named exclude.list:

Content of exclude.list:

a
b.*
tmp/g

Then run this command:

rsync
rsync -av --exclude-from=exclude.list /home/mysql/backup /home/mysql/backup2/

Summary

In this post, we explored how to use the rsync command to copy files recursively while excluding specific file types or patterns. The --exclude option is particularly useful for filtering out unwanted files during the copy process. Additionally, we discussed other related options like --exclude-from, --include, and --include-from for more advanced use cases. This method is efficient and works seamlessly on both Linux and MacOS systems.

Final Words + More Resources

My intention with this article was to help others who might be considering solving such a problem. So I hope that’s been the case here. If you still have any questions, don’t hesitate to ask me by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!