stinaq
stinaq

Reputation: 1284

Exclude only specific folder in tar command

I want to tar a directory that looks like this:

dir
└── workspace
└── node_modules
└── subfolder
    └── workspace
    └── node_modules
    └── other_folder

I want to exclude all folders named node_modules and exclude the top level folder called workspace, but no sub folders called workspace. So what I want to end up with is this:

dir
└── subfolder
    └── workspace
    └── other_folder

I'm running this command: tar -czf ./output.tar.gz --exclude=node_modules --exclude=./workspace dir/.

But it's removing all folders called workspace and node_modules, so I instead end up with this:

dir
└── subfolder
    └── other_folder

How do I remove only the specific workspace folder that I want, and not all folders with the same name?

Upvotes: 3

Views: 5277

Answers (2)

dash-o
dash-o

Reputation: 14422

For the required case, possible to use tar excludes:

  • --exclude dir/./folder -- apply to folder directly under dir
  • --exclude folder -- will exclude folder anywhere in the tree

Should be possible to use:

tar -czf ./output.tar.gz --exclude=node_modules --exclude=dir/./workspace dir/.

Of course possible to use --files-from, and to generate the list using another tool. This is usually preferred when the list could be large number of files, vs using xargs.

find dir/. -type f ... | tar cvz ./output.tar.gz -T-

Upvotes: 2

KamilCuk
KamilCuk

Reputation: 140900

find has many, many, many options for including, excluding paths, files, directories, generally filtering options however you want to.

For your case I think it would be:

# exclude all folders named node_modules
# exclude the top level folder called workspace
# but no sub folders called workspace
find dir -type f \
    -not -regex '.*/node_modules/.*' -a \
    -not -regex 'dir/workspace/.*' \
    -exec tar -czf ./output.tar.gz {} +

You may prefer instead of -exec for example find ... -print0 | xargs -0 tar -czf ./output.tar.gz. I think the best would be find ... -print0 | tar -czf ./output.tar.gz --null -T - as it will not fail if there are too many files, ie. too many arguments to pass to tar, I think.

I recreated dir directory with:

while read l; do
    mkdir -p "$(dirname "$l")"
    touch "$l"
done <<EOF
dir/workspace/1.txt
dir/node_modules/2.txt
dir/subfolder/workspace/3.txt
dir/subfolder/node_modules/4.txt
dir/subfolder/other_folder/5.txt
EOF

then tested on repl and the tar -tf ./output.tar.gz prints:

dir/subfolder/workspace/3.txt
dir/subfolder/other_folder/5.txt

Upvotes: 1

Related Questions