4

Folder structure:

etc (dir)
deploy (dir)
src (dir)
config (dir)
dist
 ├- config (dir) 
 ├- index.js

What I'd like to do is pack up everything except the root config folder and place it in a tar in deploy. It's important that the dist/config folder be present in the output. Started with:

tar -czf deploy/deploy.gz   --exclude=deploy  --exclude="./config/"  ./*

$ l ./deploy/deploy0/dist 
index.js
router.js
test

But that results in a missing dist/config. The only way I can get dist/config to come over is if I don't try to exclude anything named config:

tar -czf deploy/deploy.gz   --exclude=deploy   ./*

$ l ./deploy/deploy1/dist 
config
index.js
router.js
test

OSX and CentOS (dev and build). The man for tar makes me think this is not possible.

I worked around this by just deleting folders I don't want, since this is in a build environment and the files are disposable.

3 Answers 3

1

You could use find to create your arguments - a bit longish though:

 find -mindepth 1 ! -wholename './config' ! -wholename './config/*'

mindepth 1 to exclude ., and two wholename exclutions for the directory itself, as well as its contents.

tar -xzf deploy/deploy.gz --exclude="deploy" \
$( find -mindepth 1 ! -wholename './config' ! -wholename './config/*' )
0

Make sure to put --exclude options before the source, destination args

tar --exclude=deploy --exclude="./config" -cvz deploy/deploy.gz .
2
  • tar: Option --exclude./config is not supported
    – jcollum
    Oct 20, 2016 at 22:15
  • fixed this typo to --exclude="./config"
    – Michael D.
    Oct 20, 2016 at 22:19
0

With that skeleton directory tree:

mkdir -p src config dist/config

GNU tar seems to do what you want if you use --exclude="./config" (without the trailing slash):

$ tar --version
tar (GNU tar) 1.27.1
$ tar cf - --exclude="./config" ./* | tar tf -
./dist/
./dist/config/
./src/

However, the tar on my OS X (bsdtar 2.8.3 - libarchive 2.8.3) seems to drop both copies of config with that same command line.

So, one way to work around it seems to use GNU tar. :)

Another would be to make the archive one directory level higher, and include the top-level directory in it (as is customary with Unix software), so we can use its name on the exclude:

$ cd ..
$ tar cf - --exclude="dir/config" dir/* | tar tf -
dir/dist/
dir/dist/config/
dir/src/

Or, if you have a shell that supports it, use extglob to match everything but the one name:

$ shopt -s extglob
$ tar cf - ./!(config)  | tar tf -
./dist/
./dist/config/
./src/

Or use any other way to remove one item from the list of file names, which should be simple if you know your top-level file names don't contain anything more special than alphanumerics (especially no whitespace).

2
  • "Another would be to make the archive one directory level higher" unfortunately not an option in a build system -- I'm locked in to that directory by design, unable to edit directories outside of it
    – jcollum
    Oct 21, 2016 at 14:51
  • Add ^ to your top-level --exclude like this: tar cf - --exclude="^config" ./* | tar tf - I had the same problem on macos and this fixes that. Later configs won't match, because the ^ causes a match only at the start of the line, and later ones will have path prefixes.
    – jaygooby
    Oct 4, 2019 at 11:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.