Correct syntax for including .* directories with tar











up vote
2
down vote

favorite
1












I'm trying to include files that match */*/.thisdirectory/* in a tar archive. What's the correct syntax? Apparently this is not:



> find .
.
./bar
./bar/.a
./bar/.a/baz
./foo
./foo/.a
> tar --include "*[.]a*" -cvf a.tar .
>









share|improve this question


























    up vote
    2
    down vote

    favorite
    1












    I'm trying to include files that match */*/.thisdirectory/* in a tar archive. What's the correct syntax? Apparently this is not:



    > find .
    .
    ./bar
    ./bar/.a
    ./bar/.a/baz
    ./foo
    ./foo/.a
    > tar --include "*[.]a*" -cvf a.tar .
    >









    share|improve this question
























      up vote
      2
      down vote

      favorite
      1









      up vote
      2
      down vote

      favorite
      1






      1





      I'm trying to include files that match */*/.thisdirectory/* in a tar archive. What's the correct syntax? Apparently this is not:



      > find .
      .
      ./bar
      ./bar/.a
      ./bar/.a/baz
      ./foo
      ./foo/.a
      > tar --include "*[.]a*" -cvf a.tar .
      >









      share|improve this question













      I'm trying to include files that match */*/.thisdirectory/* in a tar archive. What's the correct syntax? Apparently this is not:



      > find .
      .
      ./bar
      ./bar/.a
      ./bar/.a/baz
      ./foo
      ./foo/.a
      > tar --include "*[.]a*" -cvf a.tar .
      >






      tar






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked May 6 '16 at 23:45









      cbmanica

      1336




      1336






















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          1
          down vote













          I'm assuming you're using FreeBSD tar¹ as this is the only implementation I know with a --include option.



          When you pass --include, only explicitly included files are traversed. When building an archive, if a directory isn't traversed then neither it nor any of its contents can be included. Since you're tarring . but not including ., the sole command line argument doesn't get included, and you get an empty archive.



          To reach the .a directories, you would need to include all the parent directories. The thing is, if you do that, then all of their contents will be included as well. You can use --exclude to exclude them, but then you need an exclude pattern that doesn't exclude the dot directories that you want to include. At this point --include is no longer of any use. The --include option is rarely useful when creating an archive, it's rather more useful when copying part of an existing archive (because when doing that, there's no recursive traversal, just iteration through the list of members of the input archive).



          tar --exclude='./*/[!.]*' -cvf a.tar .


          Note that all files in the toplevel directory are included. I don't think there's a way to include only those directories that will have non-empty contents.



          To get only the ./*/.* directories and nothing else (in particular not their parent directories), you need to pass them as arguments to tar, rather than let tar recurse to find them.



          tar -cvf a.tar ./*/.[!.]*/


          Remove the trailing slash to include files that aren't directories (or symlinks to directories). Add ./*/..?*/ to include directories whose name begins with .. if you have those.



          ¹ Possibly under a different operating system.






          share|improve this answer




























            up vote
            1
            down vote













            If your shell is bash, you can use the GLOBIGNORE variable to hide the . and .. directories. This does automatically also set the dotglob option, so * now matches both hidden and non-hidden files:



            GLOBIGNORE=".:.."
            tar czf tarball-with-hidden-files.tgz directory/*


            To expand on this a bit: by default, * does not match hidden files (files starting with a .), which includes the current (.) and parent (..) directories of any directory. If you want a glob (e. g. a command line wildcard) to match them, you need to set the dotglob option, but this can cause really bad things to happen if .. matches * and you do something like rm -fr /home/olduser/* (because olduser/.. matches, which is /home/ and now you've just fried everyones' home directories. Which is where GLOBIGNORE comes into play- it blacklists things from matching wildcards. As a really simple use-case:



            ghoti@home:~/scratch$ ls -ld ?dotfile
            ls: cannot access '?dotfile': No such file or directory
            ghoti@home:~/scratch$ touch _dotfile .dotfile
            ghoti@home:~/scratch$ ls -ld ?dotfile
            -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
            ghoti@home:~/scratch$ GLOBIGNORE=".:.."
            ghoti@home:~/scratch$ ls -ld ?dotfile
            -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
            -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 .dotfile


            What does this mean for you? Well, as in the quick example at the top of this answer, once you set GLOBIGNORE to ignore . and .., you can use * to match hidden directories like the ones you're trying to archive:



            tar czf mytarball.tgz directory/*  # this will include things like directory/.hiddenfile


            To point this at your specific example of a directory called .a:



            ghoti@home:~/scratch$ mkdir -p example example/foo/.a example/bar/.a example/foo/_a example/bar/_a
            ghoti@home:~/scratch$ touch example/{foo,bar}/{.,_}a/file
            ghoti@home:~/scratch$ find example/
            example/
            example/foo
            example/foo/_a
            example/foo/_a/file
            example/foo/.a
            example/foo/.a/file
            example/bar
            example/bar/_a
            example/bar/_a/file
            example/bar/.a
            example/bar/.a/file
            ghoti@home:~/scratch$ GLOBIGNORE=".:.."
            ghoti@home:~/scratch$ tar cvzf withdotfiles.tgz example/*/?a
            example/bar/_a/
            example/bar/_a/file
            example/bar/.a/
            example/bar/.a/file
            example/foo/_a/
            example/foo/_a/file
            example/foo/.a/
            example/foo/.a/file
            ghoti@home:~/scratch$ unset GLOBIGNORE
            ghoti@home:~/scratch$ tar cvzf withoutdotfiles.tgz example/*/?a
            example/bar/_a/
            example/bar/_a/file
            example/foo/_a/
            example/foo/_a/file





            share|improve this answer























            • I must be missing something, because that doesn't improve the situation at all: > GLOBIGNORE=".:.." tar --include "*[.]a*" -cvf a.tar . > The .* directories get included just fine without --include but trying to restrict what gets tarred fails utterly...
              – cbmanica
              May 6 '16 at 23:53












            • @cbmanica the command you show in no way resembles DopeGhoti's example nor does it */*/.thisdirectory/* so clarifications are needed on what files you want to include.
              – Julie Pelletier
              May 6 '16 at 23:58










            • I thought it was extremely clear that I want to include files that match ".foo" from a current directory. If my command didn't match that, maybe that's because I at no time indicated I was dealing with a tgz.
              – cbmanica
              May 7 '16 at 0:01










            • I suppose given that find . | grep "[.]thisdirectory" > files; tar -cf my.tar -T files does what I want, this is all academic, but I get tired of SO being so willfully pedantic in response to all questions.
              – cbmanica
              May 7 '16 at 0:02










            • Without specific questions, it's exceedingly difficult to give specific answers.
              – DopeGhoti
              May 7 '16 at 0:06


















            up vote
            0
            down vote













            Rather jumping on an old horse here, but, since I can't find any evidence of anyone pointing out the apparently "intended" way that this should be done with tar:



            The issue, as has been noted elsewhere, is that tar is quite literal with "--include", and it won't traverse into directories foo and bar to find your .a files, if the --include filters them off first.



            The clue to the trick to using tar as you'd like to use it /is/ included in the man page, but it's fairly well obfuscated: --include is "supposed" to be used to filter existing archives; Also, there is a magic argument @- that causes tar to treat a read from STDIN as a read from an existing archive.



            Put together, you can use one promiscuous tar statement to create an archive of everything below the current directory, and stuff it onto STDOUT. You then pipe this into a tar that's going to use the --include option, and that reads from STDIN.



            In your case, this looks something like:



            tar -cf - / | tar -cf myfiles.tar --include=".a" @-



            Soyokaze:test$ ls -lR
            total 32
            drwxr-xr-x 6 tyler staff 204 Nov 29 14:24 bar/
            drwxr-xr-x 4 tyler staff 136 Nov 29 14:23 foo/

            ./bar:
            total 0
            -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
            -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baaa.a
            -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz
            drwxr-xr-x 2 tyler staff 68 Nov 29 14:24 boos/

            ./bar/boos:
            total 0

            ./foo:
            total 0
            -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
            -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz.a

            Soyokaze:test$ tar -cf - */ | tar -cf myfiles.tar --include="*.a" @-

            Soyokaze:test$ tar -tf myfiles.tar
            bar/baa.a
            bar/baaa.a
            foo/baa.a
            foo/baz.a





            share|improve this answer





















              Your Answer








              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "106"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f281624%2fcorrect-syntax-for-including-directories-with-tar%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              1
              down vote













              I'm assuming you're using FreeBSD tar¹ as this is the only implementation I know with a --include option.



              When you pass --include, only explicitly included files are traversed. When building an archive, if a directory isn't traversed then neither it nor any of its contents can be included. Since you're tarring . but not including ., the sole command line argument doesn't get included, and you get an empty archive.



              To reach the .a directories, you would need to include all the parent directories. The thing is, if you do that, then all of their contents will be included as well. You can use --exclude to exclude them, but then you need an exclude pattern that doesn't exclude the dot directories that you want to include. At this point --include is no longer of any use. The --include option is rarely useful when creating an archive, it's rather more useful when copying part of an existing archive (because when doing that, there's no recursive traversal, just iteration through the list of members of the input archive).



              tar --exclude='./*/[!.]*' -cvf a.tar .


              Note that all files in the toplevel directory are included. I don't think there's a way to include only those directories that will have non-empty contents.



              To get only the ./*/.* directories and nothing else (in particular not their parent directories), you need to pass them as arguments to tar, rather than let tar recurse to find them.



              tar -cvf a.tar ./*/.[!.]*/


              Remove the trailing slash to include files that aren't directories (or symlinks to directories). Add ./*/..?*/ to include directories whose name begins with .. if you have those.



              ¹ Possibly under a different operating system.






              share|improve this answer

























                up vote
                1
                down vote













                I'm assuming you're using FreeBSD tar¹ as this is the only implementation I know with a --include option.



                When you pass --include, only explicitly included files are traversed. When building an archive, if a directory isn't traversed then neither it nor any of its contents can be included. Since you're tarring . but not including ., the sole command line argument doesn't get included, and you get an empty archive.



                To reach the .a directories, you would need to include all the parent directories. The thing is, if you do that, then all of their contents will be included as well. You can use --exclude to exclude them, but then you need an exclude pattern that doesn't exclude the dot directories that you want to include. At this point --include is no longer of any use. The --include option is rarely useful when creating an archive, it's rather more useful when copying part of an existing archive (because when doing that, there's no recursive traversal, just iteration through the list of members of the input archive).



                tar --exclude='./*/[!.]*' -cvf a.tar .


                Note that all files in the toplevel directory are included. I don't think there's a way to include only those directories that will have non-empty contents.



                To get only the ./*/.* directories and nothing else (in particular not their parent directories), you need to pass them as arguments to tar, rather than let tar recurse to find them.



                tar -cvf a.tar ./*/.[!.]*/


                Remove the trailing slash to include files that aren't directories (or symlinks to directories). Add ./*/..?*/ to include directories whose name begins with .. if you have those.



                ¹ Possibly under a different operating system.






                share|improve this answer























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  I'm assuming you're using FreeBSD tar¹ as this is the only implementation I know with a --include option.



                  When you pass --include, only explicitly included files are traversed. When building an archive, if a directory isn't traversed then neither it nor any of its contents can be included. Since you're tarring . but not including ., the sole command line argument doesn't get included, and you get an empty archive.



                  To reach the .a directories, you would need to include all the parent directories. The thing is, if you do that, then all of their contents will be included as well. You can use --exclude to exclude them, but then you need an exclude pattern that doesn't exclude the dot directories that you want to include. At this point --include is no longer of any use. The --include option is rarely useful when creating an archive, it's rather more useful when copying part of an existing archive (because when doing that, there's no recursive traversal, just iteration through the list of members of the input archive).



                  tar --exclude='./*/[!.]*' -cvf a.tar .


                  Note that all files in the toplevel directory are included. I don't think there's a way to include only those directories that will have non-empty contents.



                  To get only the ./*/.* directories and nothing else (in particular not their parent directories), you need to pass them as arguments to tar, rather than let tar recurse to find them.



                  tar -cvf a.tar ./*/.[!.]*/


                  Remove the trailing slash to include files that aren't directories (or symlinks to directories). Add ./*/..?*/ to include directories whose name begins with .. if you have those.



                  ¹ Possibly under a different operating system.






                  share|improve this answer












                  I'm assuming you're using FreeBSD tar¹ as this is the only implementation I know with a --include option.



                  When you pass --include, only explicitly included files are traversed. When building an archive, if a directory isn't traversed then neither it nor any of its contents can be included. Since you're tarring . but not including ., the sole command line argument doesn't get included, and you get an empty archive.



                  To reach the .a directories, you would need to include all the parent directories. The thing is, if you do that, then all of their contents will be included as well. You can use --exclude to exclude them, but then you need an exclude pattern that doesn't exclude the dot directories that you want to include. At this point --include is no longer of any use. The --include option is rarely useful when creating an archive, it's rather more useful when copying part of an existing archive (because when doing that, there's no recursive traversal, just iteration through the list of members of the input archive).



                  tar --exclude='./*/[!.]*' -cvf a.tar .


                  Note that all files in the toplevel directory are included. I don't think there's a way to include only those directories that will have non-empty contents.



                  To get only the ./*/.* directories and nothing else (in particular not their parent directories), you need to pass them as arguments to tar, rather than let tar recurse to find them.



                  tar -cvf a.tar ./*/.[!.]*/


                  Remove the trailing slash to include files that aren't directories (or symlinks to directories). Add ./*/..?*/ to include directories whose name begins with .. if you have those.



                  ¹ Possibly under a different operating system.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered May 7 '16 at 23:09









                  Gilles

                  524k12610481578




                  524k12610481578
























                      up vote
                      1
                      down vote













                      If your shell is bash, you can use the GLOBIGNORE variable to hide the . and .. directories. This does automatically also set the dotglob option, so * now matches both hidden and non-hidden files:



                      GLOBIGNORE=".:.."
                      tar czf tarball-with-hidden-files.tgz directory/*


                      To expand on this a bit: by default, * does not match hidden files (files starting with a .), which includes the current (.) and parent (..) directories of any directory. If you want a glob (e. g. a command line wildcard) to match them, you need to set the dotglob option, but this can cause really bad things to happen if .. matches * and you do something like rm -fr /home/olduser/* (because olduser/.. matches, which is /home/ and now you've just fried everyones' home directories. Which is where GLOBIGNORE comes into play- it blacklists things from matching wildcards. As a really simple use-case:



                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      ls: cannot access '?dotfile': No such file or directory
                      ghoti@home:~/scratch$ touch _dotfile .dotfile
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 .dotfile


                      What does this mean for you? Well, as in the quick example at the top of this answer, once you set GLOBIGNORE to ignore . and .., you can use * to match hidden directories like the ones you're trying to archive:



                      tar czf mytarball.tgz directory/*  # this will include things like directory/.hiddenfile


                      To point this at your specific example of a directory called .a:



                      ghoti@home:~/scratch$ mkdir -p example example/foo/.a example/bar/.a example/foo/_a example/bar/_a
                      ghoti@home:~/scratch$ touch example/{foo,bar}/{.,_}a/file
                      ghoti@home:~/scratch$ find example/
                      example/
                      example/foo
                      example/foo/_a
                      example/foo/_a/file
                      example/foo/.a
                      example/foo/.a/file
                      example/bar
                      example/bar/_a
                      example/bar/_a/file
                      example/bar/.a
                      example/bar/.a/file
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ tar cvzf withdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/bar/.a/
                      example/bar/.a/file
                      example/foo/_a/
                      example/foo/_a/file
                      example/foo/.a/
                      example/foo/.a/file
                      ghoti@home:~/scratch$ unset GLOBIGNORE
                      ghoti@home:~/scratch$ tar cvzf withoutdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/foo/_a/
                      example/foo/_a/file





                      share|improve this answer























                      • I must be missing something, because that doesn't improve the situation at all: > GLOBIGNORE=".:.." tar --include "*[.]a*" -cvf a.tar . > The .* directories get included just fine without --include but trying to restrict what gets tarred fails utterly...
                        – cbmanica
                        May 6 '16 at 23:53












                      • @cbmanica the command you show in no way resembles DopeGhoti's example nor does it */*/.thisdirectory/* so clarifications are needed on what files you want to include.
                        – Julie Pelletier
                        May 6 '16 at 23:58










                      • I thought it was extremely clear that I want to include files that match ".foo" from a current directory. If my command didn't match that, maybe that's because I at no time indicated I was dealing with a tgz.
                        – cbmanica
                        May 7 '16 at 0:01










                      • I suppose given that find . | grep "[.]thisdirectory" > files; tar -cf my.tar -T files does what I want, this is all academic, but I get tired of SO being so willfully pedantic in response to all questions.
                        – cbmanica
                        May 7 '16 at 0:02










                      • Without specific questions, it's exceedingly difficult to give specific answers.
                        – DopeGhoti
                        May 7 '16 at 0:06















                      up vote
                      1
                      down vote













                      If your shell is bash, you can use the GLOBIGNORE variable to hide the . and .. directories. This does automatically also set the dotglob option, so * now matches both hidden and non-hidden files:



                      GLOBIGNORE=".:.."
                      tar czf tarball-with-hidden-files.tgz directory/*


                      To expand on this a bit: by default, * does not match hidden files (files starting with a .), which includes the current (.) and parent (..) directories of any directory. If you want a glob (e. g. a command line wildcard) to match them, you need to set the dotglob option, but this can cause really bad things to happen if .. matches * and you do something like rm -fr /home/olduser/* (because olduser/.. matches, which is /home/ and now you've just fried everyones' home directories. Which is where GLOBIGNORE comes into play- it blacklists things from matching wildcards. As a really simple use-case:



                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      ls: cannot access '?dotfile': No such file or directory
                      ghoti@home:~/scratch$ touch _dotfile .dotfile
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 .dotfile


                      What does this mean for you? Well, as in the quick example at the top of this answer, once you set GLOBIGNORE to ignore . and .., you can use * to match hidden directories like the ones you're trying to archive:



                      tar czf mytarball.tgz directory/*  # this will include things like directory/.hiddenfile


                      To point this at your specific example of a directory called .a:



                      ghoti@home:~/scratch$ mkdir -p example example/foo/.a example/bar/.a example/foo/_a example/bar/_a
                      ghoti@home:~/scratch$ touch example/{foo,bar}/{.,_}a/file
                      ghoti@home:~/scratch$ find example/
                      example/
                      example/foo
                      example/foo/_a
                      example/foo/_a/file
                      example/foo/.a
                      example/foo/.a/file
                      example/bar
                      example/bar/_a
                      example/bar/_a/file
                      example/bar/.a
                      example/bar/.a/file
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ tar cvzf withdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/bar/.a/
                      example/bar/.a/file
                      example/foo/_a/
                      example/foo/_a/file
                      example/foo/.a/
                      example/foo/.a/file
                      ghoti@home:~/scratch$ unset GLOBIGNORE
                      ghoti@home:~/scratch$ tar cvzf withoutdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/foo/_a/
                      example/foo/_a/file





                      share|improve this answer























                      • I must be missing something, because that doesn't improve the situation at all: > GLOBIGNORE=".:.." tar --include "*[.]a*" -cvf a.tar . > The .* directories get included just fine without --include but trying to restrict what gets tarred fails utterly...
                        – cbmanica
                        May 6 '16 at 23:53












                      • @cbmanica the command you show in no way resembles DopeGhoti's example nor does it */*/.thisdirectory/* so clarifications are needed on what files you want to include.
                        – Julie Pelletier
                        May 6 '16 at 23:58










                      • I thought it was extremely clear that I want to include files that match ".foo" from a current directory. If my command didn't match that, maybe that's because I at no time indicated I was dealing with a tgz.
                        – cbmanica
                        May 7 '16 at 0:01










                      • I suppose given that find . | grep "[.]thisdirectory" > files; tar -cf my.tar -T files does what I want, this is all academic, but I get tired of SO being so willfully pedantic in response to all questions.
                        – cbmanica
                        May 7 '16 at 0:02










                      • Without specific questions, it's exceedingly difficult to give specific answers.
                        – DopeGhoti
                        May 7 '16 at 0:06













                      up vote
                      1
                      down vote










                      up vote
                      1
                      down vote









                      If your shell is bash, you can use the GLOBIGNORE variable to hide the . and .. directories. This does automatically also set the dotglob option, so * now matches both hidden and non-hidden files:



                      GLOBIGNORE=".:.."
                      tar czf tarball-with-hidden-files.tgz directory/*


                      To expand on this a bit: by default, * does not match hidden files (files starting with a .), which includes the current (.) and parent (..) directories of any directory. If you want a glob (e. g. a command line wildcard) to match them, you need to set the dotglob option, but this can cause really bad things to happen if .. matches * and you do something like rm -fr /home/olduser/* (because olduser/.. matches, which is /home/ and now you've just fried everyones' home directories. Which is where GLOBIGNORE comes into play- it blacklists things from matching wildcards. As a really simple use-case:



                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      ls: cannot access '?dotfile': No such file or directory
                      ghoti@home:~/scratch$ touch _dotfile .dotfile
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 .dotfile


                      What does this mean for you? Well, as in the quick example at the top of this answer, once you set GLOBIGNORE to ignore . and .., you can use * to match hidden directories like the ones you're trying to archive:



                      tar czf mytarball.tgz directory/*  # this will include things like directory/.hiddenfile


                      To point this at your specific example of a directory called .a:



                      ghoti@home:~/scratch$ mkdir -p example example/foo/.a example/bar/.a example/foo/_a example/bar/_a
                      ghoti@home:~/scratch$ touch example/{foo,bar}/{.,_}a/file
                      ghoti@home:~/scratch$ find example/
                      example/
                      example/foo
                      example/foo/_a
                      example/foo/_a/file
                      example/foo/.a
                      example/foo/.a/file
                      example/bar
                      example/bar/_a
                      example/bar/_a/file
                      example/bar/.a
                      example/bar/.a/file
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ tar cvzf withdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/bar/.a/
                      example/bar/.a/file
                      example/foo/_a/
                      example/foo/_a/file
                      example/foo/.a/
                      example/foo/.a/file
                      ghoti@home:~/scratch$ unset GLOBIGNORE
                      ghoti@home:~/scratch$ tar cvzf withoutdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/foo/_a/
                      example/foo/_a/file





                      share|improve this answer














                      If your shell is bash, you can use the GLOBIGNORE variable to hide the . and .. directories. This does automatically also set the dotglob option, so * now matches both hidden and non-hidden files:



                      GLOBIGNORE=".:.."
                      tar czf tarball-with-hidden-files.tgz directory/*


                      To expand on this a bit: by default, * does not match hidden files (files starting with a .), which includes the current (.) and parent (..) directories of any directory. If you want a glob (e. g. a command line wildcard) to match them, you need to set the dotglob option, but this can cause really bad things to happen if .. matches * and you do something like rm -fr /home/olduser/* (because olduser/.. matches, which is /home/ and now you've just fried everyones' home directories. Which is where GLOBIGNORE comes into play- it blacklists things from matching wildcards. As a really simple use-case:



                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      ls: cannot access '?dotfile': No such file or directory
                      ghoti@home:~/scratch$ touch _dotfile .dotfile
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ ls -ld ?dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 _dotfile
                      -rw-rw-r-- 1 ghoti ghoti 0 May 6 16:58 .dotfile


                      What does this mean for you? Well, as in the quick example at the top of this answer, once you set GLOBIGNORE to ignore . and .., you can use * to match hidden directories like the ones you're trying to archive:



                      tar czf mytarball.tgz directory/*  # this will include things like directory/.hiddenfile


                      To point this at your specific example of a directory called .a:



                      ghoti@home:~/scratch$ mkdir -p example example/foo/.a example/bar/.a example/foo/_a example/bar/_a
                      ghoti@home:~/scratch$ touch example/{foo,bar}/{.,_}a/file
                      ghoti@home:~/scratch$ find example/
                      example/
                      example/foo
                      example/foo/_a
                      example/foo/_a/file
                      example/foo/.a
                      example/foo/.a/file
                      example/bar
                      example/bar/_a
                      example/bar/_a/file
                      example/bar/.a
                      example/bar/.a/file
                      ghoti@home:~/scratch$ GLOBIGNORE=".:.."
                      ghoti@home:~/scratch$ tar cvzf withdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/bar/.a/
                      example/bar/.a/file
                      example/foo/_a/
                      example/foo/_a/file
                      example/foo/.a/
                      example/foo/.a/file
                      ghoti@home:~/scratch$ unset GLOBIGNORE
                      ghoti@home:~/scratch$ tar cvzf withoutdotfiles.tgz example/*/?a
                      example/bar/_a/
                      example/bar/_a/file
                      example/foo/_a/
                      example/foo/_a/file






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 7 '16 at 23:11









                      Gilles

                      524k12610481578




                      524k12610481578










                      answered May 6 '16 at 23:50









                      DopeGhoti

                      42.9k55382




                      42.9k55382












                      • I must be missing something, because that doesn't improve the situation at all: > GLOBIGNORE=".:.." tar --include "*[.]a*" -cvf a.tar . > The .* directories get included just fine without --include but trying to restrict what gets tarred fails utterly...
                        – cbmanica
                        May 6 '16 at 23:53












                      • @cbmanica the command you show in no way resembles DopeGhoti's example nor does it */*/.thisdirectory/* so clarifications are needed on what files you want to include.
                        – Julie Pelletier
                        May 6 '16 at 23:58










                      • I thought it was extremely clear that I want to include files that match ".foo" from a current directory. If my command didn't match that, maybe that's because I at no time indicated I was dealing with a tgz.
                        – cbmanica
                        May 7 '16 at 0:01










                      • I suppose given that find . | grep "[.]thisdirectory" > files; tar -cf my.tar -T files does what I want, this is all academic, but I get tired of SO being so willfully pedantic in response to all questions.
                        – cbmanica
                        May 7 '16 at 0:02










                      • Without specific questions, it's exceedingly difficult to give specific answers.
                        – DopeGhoti
                        May 7 '16 at 0:06


















                      • I must be missing something, because that doesn't improve the situation at all: > GLOBIGNORE=".:.." tar --include "*[.]a*" -cvf a.tar . > The .* directories get included just fine without --include but trying to restrict what gets tarred fails utterly...
                        – cbmanica
                        May 6 '16 at 23:53












                      • @cbmanica the command you show in no way resembles DopeGhoti's example nor does it */*/.thisdirectory/* so clarifications are needed on what files you want to include.
                        – Julie Pelletier
                        May 6 '16 at 23:58










                      • I thought it was extremely clear that I want to include files that match ".foo" from a current directory. If my command didn't match that, maybe that's because I at no time indicated I was dealing with a tgz.
                        – cbmanica
                        May 7 '16 at 0:01










                      • I suppose given that find . | grep "[.]thisdirectory" > files; tar -cf my.tar -T files does what I want, this is all academic, but I get tired of SO being so willfully pedantic in response to all questions.
                        – cbmanica
                        May 7 '16 at 0:02










                      • Without specific questions, it's exceedingly difficult to give specific answers.
                        – DopeGhoti
                        May 7 '16 at 0:06
















                      I must be missing something, because that doesn't improve the situation at all: > GLOBIGNORE=".:.." tar --include "*[.]a*" -cvf a.tar . > The .* directories get included just fine without --include but trying to restrict what gets tarred fails utterly...
                      – cbmanica
                      May 6 '16 at 23:53






                      I must be missing something, because that doesn't improve the situation at all: > GLOBIGNORE=".:.." tar --include "*[.]a*" -cvf a.tar . > The .* directories get included just fine without --include but trying to restrict what gets tarred fails utterly...
                      – cbmanica
                      May 6 '16 at 23:53














                      @cbmanica the command you show in no way resembles DopeGhoti's example nor does it */*/.thisdirectory/* so clarifications are needed on what files you want to include.
                      – Julie Pelletier
                      May 6 '16 at 23:58




                      @cbmanica the command you show in no way resembles DopeGhoti's example nor does it */*/.thisdirectory/* so clarifications are needed on what files you want to include.
                      – Julie Pelletier
                      May 6 '16 at 23:58












                      I thought it was extremely clear that I want to include files that match ".foo" from a current directory. If my command didn't match that, maybe that's because I at no time indicated I was dealing with a tgz.
                      – cbmanica
                      May 7 '16 at 0:01




                      I thought it was extremely clear that I want to include files that match ".foo" from a current directory. If my command didn't match that, maybe that's because I at no time indicated I was dealing with a tgz.
                      – cbmanica
                      May 7 '16 at 0:01












                      I suppose given that find . | grep "[.]thisdirectory" > files; tar -cf my.tar -T files does what I want, this is all academic, but I get tired of SO being so willfully pedantic in response to all questions.
                      – cbmanica
                      May 7 '16 at 0:02




                      I suppose given that find . | grep "[.]thisdirectory" > files; tar -cf my.tar -T files does what I want, this is all academic, but I get tired of SO being so willfully pedantic in response to all questions.
                      – cbmanica
                      May 7 '16 at 0:02












                      Without specific questions, it's exceedingly difficult to give specific answers.
                      – DopeGhoti
                      May 7 '16 at 0:06




                      Without specific questions, it's exceedingly difficult to give specific answers.
                      – DopeGhoti
                      May 7 '16 at 0:06










                      up vote
                      0
                      down vote













                      Rather jumping on an old horse here, but, since I can't find any evidence of anyone pointing out the apparently "intended" way that this should be done with tar:



                      The issue, as has been noted elsewhere, is that tar is quite literal with "--include", and it won't traverse into directories foo and bar to find your .a files, if the --include filters them off first.



                      The clue to the trick to using tar as you'd like to use it /is/ included in the man page, but it's fairly well obfuscated: --include is "supposed" to be used to filter existing archives; Also, there is a magic argument @- that causes tar to treat a read from STDIN as a read from an existing archive.



                      Put together, you can use one promiscuous tar statement to create an archive of everything below the current directory, and stuff it onto STDOUT. You then pipe this into a tar that's going to use the --include option, and that reads from STDIN.



                      In your case, this looks something like:



                      tar -cf - / | tar -cf myfiles.tar --include=".a" @-



                      Soyokaze:test$ ls -lR
                      total 32
                      drwxr-xr-x 6 tyler staff 204 Nov 29 14:24 bar/
                      drwxr-xr-x 4 tyler staff 136 Nov 29 14:23 foo/

                      ./bar:
                      total 0
                      -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                      -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baaa.a
                      -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz
                      drwxr-xr-x 2 tyler staff 68 Nov 29 14:24 boos/

                      ./bar/boos:
                      total 0

                      ./foo:
                      total 0
                      -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                      -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz.a

                      Soyokaze:test$ tar -cf - */ | tar -cf myfiles.tar --include="*.a" @-

                      Soyokaze:test$ tar -tf myfiles.tar
                      bar/baa.a
                      bar/baaa.a
                      foo/baa.a
                      foo/baz.a





                      share|improve this answer

























                        up vote
                        0
                        down vote













                        Rather jumping on an old horse here, but, since I can't find any evidence of anyone pointing out the apparently "intended" way that this should be done with tar:



                        The issue, as has been noted elsewhere, is that tar is quite literal with "--include", and it won't traverse into directories foo and bar to find your .a files, if the --include filters them off first.



                        The clue to the trick to using tar as you'd like to use it /is/ included in the man page, but it's fairly well obfuscated: --include is "supposed" to be used to filter existing archives; Also, there is a magic argument @- that causes tar to treat a read from STDIN as a read from an existing archive.



                        Put together, you can use one promiscuous tar statement to create an archive of everything below the current directory, and stuff it onto STDOUT. You then pipe this into a tar that's going to use the --include option, and that reads from STDIN.



                        In your case, this looks something like:



                        tar -cf - / | tar -cf myfiles.tar --include=".a" @-



                        Soyokaze:test$ ls -lR
                        total 32
                        drwxr-xr-x 6 tyler staff 204 Nov 29 14:24 bar/
                        drwxr-xr-x 4 tyler staff 136 Nov 29 14:23 foo/

                        ./bar:
                        total 0
                        -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                        -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baaa.a
                        -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz
                        drwxr-xr-x 2 tyler staff 68 Nov 29 14:24 boos/

                        ./bar/boos:
                        total 0

                        ./foo:
                        total 0
                        -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                        -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz.a

                        Soyokaze:test$ tar -cf - */ | tar -cf myfiles.tar --include="*.a" @-

                        Soyokaze:test$ tar -tf myfiles.tar
                        bar/baa.a
                        bar/baaa.a
                        foo/baa.a
                        foo/baz.a





                        share|improve this answer























                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          Rather jumping on an old horse here, but, since I can't find any evidence of anyone pointing out the apparently "intended" way that this should be done with tar:



                          The issue, as has been noted elsewhere, is that tar is quite literal with "--include", and it won't traverse into directories foo and bar to find your .a files, if the --include filters them off first.



                          The clue to the trick to using tar as you'd like to use it /is/ included in the man page, but it's fairly well obfuscated: --include is "supposed" to be used to filter existing archives; Also, there is a magic argument @- that causes tar to treat a read from STDIN as a read from an existing archive.



                          Put together, you can use one promiscuous tar statement to create an archive of everything below the current directory, and stuff it onto STDOUT. You then pipe this into a tar that's going to use the --include option, and that reads from STDIN.



                          In your case, this looks something like:



                          tar -cf - / | tar -cf myfiles.tar --include=".a" @-



                          Soyokaze:test$ ls -lR
                          total 32
                          drwxr-xr-x 6 tyler staff 204 Nov 29 14:24 bar/
                          drwxr-xr-x 4 tyler staff 136 Nov 29 14:23 foo/

                          ./bar:
                          total 0
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baaa.a
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz
                          drwxr-xr-x 2 tyler staff 68 Nov 29 14:24 boos/

                          ./bar/boos:
                          total 0

                          ./foo:
                          total 0
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz.a

                          Soyokaze:test$ tar -cf - */ | tar -cf myfiles.tar --include="*.a" @-

                          Soyokaze:test$ tar -tf myfiles.tar
                          bar/baa.a
                          bar/baaa.a
                          foo/baa.a
                          foo/baz.a





                          share|improve this answer












                          Rather jumping on an old horse here, but, since I can't find any evidence of anyone pointing out the apparently "intended" way that this should be done with tar:



                          The issue, as has been noted elsewhere, is that tar is quite literal with "--include", and it won't traverse into directories foo and bar to find your .a files, if the --include filters them off first.



                          The clue to the trick to using tar as you'd like to use it /is/ included in the man page, but it's fairly well obfuscated: --include is "supposed" to be used to filter existing archives; Also, there is a magic argument @- that causes tar to treat a read from STDIN as a read from an existing archive.



                          Put together, you can use one promiscuous tar statement to create an archive of everything below the current directory, and stuff it onto STDOUT. You then pipe this into a tar that's going to use the --include option, and that reads from STDIN.



                          In your case, this looks something like:



                          tar -cf - / | tar -cf myfiles.tar --include=".a" @-



                          Soyokaze:test$ ls -lR
                          total 32
                          drwxr-xr-x 6 tyler staff 204 Nov 29 14:24 bar/
                          drwxr-xr-x 4 tyler staff 136 Nov 29 14:23 foo/

                          ./bar:
                          total 0
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baaa.a
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz
                          drwxr-xr-x 2 tyler staff 68 Nov 29 14:24 boos/

                          ./bar/boos:
                          total 0

                          ./foo:
                          total 0
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baa.a
                          -rw-r--r-- 1 tyler staff 0 Nov 29 14:23 baz.a

                          Soyokaze:test$ tar -cf - */ | tar -cf myfiles.tar --include="*.a" @-

                          Soyokaze:test$ tar -tf myfiles.tar
                          bar/baa.a
                          bar/baaa.a
                          foo/baa.a
                          foo/baz.a






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 29 at 19:33









                          W Ray

                          1




                          1






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Unix & Linux Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f281624%2fcorrect-syntax-for-including-directories-with-tar%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Morgemoulin

                              Scott Moir

                              Souastre