6

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.

5 Answers 5

2

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/*' )
1

Using a dot reference to the current directory as an archive root is an anchor:

tar --exclude='./deploy' --exclude='./config' -cvf deploy/deploy.tar .

But if you use a directory name or a wildcard, then the --anchored flag will come to the help:

tar --anchored --exclude=deploy --exclude=config -cvf deploy/deploy.tar *
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
  • 1
    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
0

You can use ./ marker at the beginning of your excluded files.

I use it this way:

tar --exclude='./build.tar.gz' --exclude='./config' -czf build.tar.gz .

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .