tar --exclude: leave files and directories out of an archive
- tool
- tar
- versions
- GNU tar 1.30+, bsdtar 3.x
- os
- linux, macos, windows
tar -czf backup.tar.gz --exclude=node_modules --exclude='*.log' project archives project without any node_modules directory and without .log files. Each --exclude takes one shell-style pattern; quote patterns that contain * so the shell does not expand them. With GNU tar, put the --exclude options before the paths: options after the paths only apply to arguments that follow them. For long lists, write the patterns in a file and pass it with --exclude-from=FILE (-X FILE).
Example
mkdir -p proj/src proj/node_modules/lib proj/.git
touch proj/src/a.js proj/node_modules/lib/i.js proj/.git/HEAD proj/app.log proj/README.md
tar -czf proj.tar.gz --exclude=node_modules --exclude='*.log' --exclude=.git proj
tar -tzf proj.tar.gz | sortOutput
proj/ proj/README.md proj/src/ proj/src/a.js
The archive keeps README.md and src/a.js. A pattern without a slash, such as node_modules, matches a file or directory of that name at any depth, and an excluded directory is skipped with everything below it.
Exclude after the paths
mkdir -p proj/node_modules/lib
touch proj/node_modules/lib/i.js proj/index.js
tar -czf late.tar.gz proj --exclude=node_modulesOutput · exit 2
tar: The following options were used after non-option arguments. These options are positional and affect only arguments that follow them. Please, rearrange them properly. tar: --exclude ‘node_modules’ has no effect tar: Exiting with failure status due to previous errors
GNU tar 1.35 refuses to let a trailing --exclude pass silently: it prints the warning above, writes the archive with node_modules and exits with status 2. Older GNU tar releases and bsdtar accept the options in any order, which is why scripts copied from elsewhere may still put them at the end.
Pattern forms
| Option | Leaves out |
|---|---|
| --exclude=node_modules | Any file or directory named node_modules, at any depth |
| --exclude='*.log' | Every name ending in .log |
| --exclude='proj/cache' | Any member path ending in proj/cache (GNU patterns are unanchored by default) |
| --exclude='proj/cache/*' | The contents of proj/cache, keeping the empty directory |
| --exclude-from=.tarignore / -X FILE | One pattern per line from a file |
| --exclude-vcs | Version control directories such as .git, .svn, .hg (GNU) |
| --exclude-vcs-ignores | Patterns read from .gitignore and similar ignore files (GNU) |
| --exclude-caches | Directories marked with a CACHEDIR.TAG file, except the tag (GNU) |
| --exclude-tag=FILE | Directories that contain FILE, except FILE itself (GNU) |
Pitfalls
- Patterns are unanchored in GNU tar.
--exclude='sub/b.log'also matchesproj/sub/b.log, and archiving./projinstead ofprojstill matchesproj/node_modules. Add--anchoredbefore the pattern when it must match from the start of the member name only. - Trailing slashes.
--exclude=node_modules/does not match in GNU tar, because member names of directories are compared without the slash. Write the name without it. - Wildcards and slashes. In GNU tar,
*in an exclude pattern also matches/by default, so--exclude='proj/*.log'excludes log files in subdirectories as well. - bsdtar (macOS, Windows tar.exe) supports
--excludeand-X, but not the--exclude-vcsfamily.
Confirm it worked
List the result and search it: tar -tzf proj.tar.gz | grep node_modules should print nothing. Compare the size with an archive made without the excludes to see how much was left out.
FAQ
Why does my --exclude have no effect?
Usually because it comes after the paths to archive. GNU tar 1.35 treats --exclude as positional and warns that it has no effect when nothing follows it. Put every --exclude before the directory names. The other common cause is a pattern with a trailing slash, which does not match the member names tar stores.
How do I exclude a directory but keep the directory itself in the archive?
Exclude its contents instead of its name, for example --exclude='proj/cache/*'. The empty cache directory is then stored, which helps when the application expects it to exist after extraction.
Can I exclude files when extracting?
Yes. --exclude also works with -x, as in tar -xzf backup.tar.gz --exclude='*.log'. The pattern is matched against the member names stored in the archive.