How to tar a list of directories only if they existHow to avoid a useless use of cat when parsing a file?How can I flatten nested .tar.gz files?Multiple tar processes writing to the same archive file at onceIs it possible to create an incremental snapshot file from an existing tar archive?Matching multiple patterns with lsDetect and remove empty directories from listtar a directory without directories insideHow to prepend a directory to files placed in a tar archive?How to make tar create a folder if it doesn't exist when creating archiveShow only the really extracted (non-skipped) files using tar

Purchased new computer from DELL with pre-installed Ubuntu. Won't boot. Should assume its an error from DELL?

What is a Casino Word™?

Does the United States guarantee any unique freedoms?

Why does putting a dot after the URL remove login information?

Identifying Vintage LEGO Instructions

Responding to Plague Engineer

"How do you solve a problem like Maria?"

Does a 4 bladed prop have almost twice the thrust of a 2 bladed prop?

Is Odin inconsistent about the powers of Mjolnir?

12V lead acid charger with LM317 not charging

Is the Folding Boat truly seaworthy?

Premier League simulation

How to continue a line in Latex in math mode?

What is an air conditioner compressor hard start kit and how does it work?

Decode a variable-length quantity

Validation and verification of mathematical models

What are the examples (applications) of the MIPs in which the objective function has nonzero coefficients for only continuous variables?

Can chords be inferred from melody alone?

How to halve redstone signal strength?

Where in ש״ס who one find the adage, “He who suggests the idea should carry it out”?

What could prevent players from leaving an island?

What does VB stand for?

Is this cheap "air conditioner" able to cool a room?

Determine Beckett Grading Service (BGS) Final Grade



How to tar a list of directories only if they exist


How to avoid a useless use of cat when parsing a file?How can I flatten nested .tar.gz files?Multiple tar processes writing to the same archive file at onceIs it possible to create an incremental snapshot file from an existing tar archive?Matching multiple patterns with lsDetect and remove empty directories from listtar a directory without directories insideHow to prepend a directory to files placed in a tar archive?How to make tar create a folder if it doesn't exist when creating archiveShow only the really extracted (non-skipped) files using tar






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








7















I have a list of directories that I want to archive. But sometimes they do not all exist.



I want to be able to create an archive by providing a list of directories, and it will only archive the existing ones, and ignore missing ones. (but should still fail if no directories exist)



This is useful for me since I am running some continuous integration and some of the processes create certain artifacts that I want to retain for the future in an archive, I know all the possible paths that can be created, but am not always sure which ones are created.



Let's say the possible paths are: here_is_a_dir here_is_another_one yet_another_dir



I usually create the archive with the following command:



tar -czf archive.tgz here_is_a_dir here_is_another_one yet_another_dir



Which of course will fail if any of the directories are missing.



Ideally, it should be a simple command, and not require a script to do.
(specifically, in my environment only sh is available, so I can't use any fancy shells like bash or others, but that is specific to my environment, and could change in the future, and answers using other shells are probably good too I think.)










share|improve this question





















  • 2





    You said below that Bash isn't an option in your environment. What shell do you have to use? Is ksh available? Or do you just have Busybox or some other POSIX sh?

    – ilkkachu
    Jul 28 at 8:32











  • @ilkkachu Thanks for the question, i will also update the original post. Only sh is available to me at the moment. But that is a limitation that only affects my specific situation, answers using other shells are still good answers I think.

    – Inbar Rose
    Jul 28 at 8:42











  • You may want to look up cpio for this.

    – mpez0
    Jul 29 at 14:50

















7















I have a list of directories that I want to archive. But sometimes they do not all exist.



I want to be able to create an archive by providing a list of directories, and it will only archive the existing ones, and ignore missing ones. (but should still fail if no directories exist)



This is useful for me since I am running some continuous integration and some of the processes create certain artifacts that I want to retain for the future in an archive, I know all the possible paths that can be created, but am not always sure which ones are created.



Let's say the possible paths are: here_is_a_dir here_is_another_one yet_another_dir



I usually create the archive with the following command:



tar -czf archive.tgz here_is_a_dir here_is_another_one yet_another_dir



Which of course will fail if any of the directories are missing.



Ideally, it should be a simple command, and not require a script to do.
(specifically, in my environment only sh is available, so I can't use any fancy shells like bash or others, but that is specific to my environment, and could change in the future, and answers using other shells are probably good too I think.)










share|improve this question





















  • 2





    You said below that Bash isn't an option in your environment. What shell do you have to use? Is ksh available? Or do you just have Busybox or some other POSIX sh?

    – ilkkachu
    Jul 28 at 8:32











  • @ilkkachu Thanks for the question, i will also update the original post. Only sh is available to me at the moment. But that is a limitation that only affects my specific situation, answers using other shells are still good answers I think.

    – Inbar Rose
    Jul 28 at 8:42











  • You may want to look up cpio for this.

    – mpez0
    Jul 29 at 14:50













7












7








7


1






I have a list of directories that I want to archive. But sometimes they do not all exist.



I want to be able to create an archive by providing a list of directories, and it will only archive the existing ones, and ignore missing ones. (but should still fail if no directories exist)



This is useful for me since I am running some continuous integration and some of the processes create certain artifacts that I want to retain for the future in an archive, I know all the possible paths that can be created, but am not always sure which ones are created.



Let's say the possible paths are: here_is_a_dir here_is_another_one yet_another_dir



I usually create the archive with the following command:



tar -czf archive.tgz here_is_a_dir here_is_another_one yet_another_dir



Which of course will fail if any of the directories are missing.



Ideally, it should be a simple command, and not require a script to do.
(specifically, in my environment only sh is available, so I can't use any fancy shells like bash or others, but that is specific to my environment, and could change in the future, and answers using other shells are probably good too I think.)










share|improve this question
















I have a list of directories that I want to archive. But sometimes they do not all exist.



I want to be able to create an archive by providing a list of directories, and it will only archive the existing ones, and ignore missing ones. (but should still fail if no directories exist)



This is useful for me since I am running some continuous integration and some of the processes create certain artifacts that I want to retain for the future in an archive, I know all the possible paths that can be created, but am not always sure which ones are created.



Let's say the possible paths are: here_is_a_dir here_is_another_one yet_another_dir



I usually create the archive with the following command:



tar -czf archive.tgz here_is_a_dir here_is_another_one yet_another_dir



Which of course will fail if any of the directories are missing.



Ideally, it should be a simple command, and not require a script to do.
(specifically, in my environment only sh is available, so I can't use any fancy shells like bash or others, but that is specific to my environment, and could change in the future, and answers using other shells are probably good too I think.)







shell-script shell ls tar






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jul 28 at 8:43







Inbar Rose

















asked Jul 28 at 7:31









Inbar RoseInbar Rose

1461 silver badge6 bronze badges




1461 silver badge6 bronze badges










  • 2





    You said below that Bash isn't an option in your environment. What shell do you have to use? Is ksh available? Or do you just have Busybox or some other POSIX sh?

    – ilkkachu
    Jul 28 at 8:32











  • @ilkkachu Thanks for the question, i will also update the original post. Only sh is available to me at the moment. But that is a limitation that only affects my specific situation, answers using other shells are still good answers I think.

    – Inbar Rose
    Jul 28 at 8:42











  • You may want to look up cpio for this.

    – mpez0
    Jul 29 at 14:50












  • 2





    You said below that Bash isn't an option in your environment. What shell do you have to use? Is ksh available? Or do you just have Busybox or some other POSIX sh?

    – ilkkachu
    Jul 28 at 8:32











  • @ilkkachu Thanks for the question, i will also update the original post. Only sh is available to me at the moment. But that is a limitation that only affects my specific situation, answers using other shells are still good answers I think.

    – Inbar Rose
    Jul 28 at 8:42











  • You may want to look up cpio for this.

    – mpez0
    Jul 29 at 14:50







2




2





You said below that Bash isn't an option in your environment. What shell do you have to use? Is ksh available? Or do you just have Busybox or some other POSIX sh?

– ilkkachu
Jul 28 at 8:32





You said below that Bash isn't an option in your environment. What shell do you have to use? Is ksh available? Or do you just have Busybox or some other POSIX sh?

– ilkkachu
Jul 28 at 8:32













@ilkkachu Thanks for the question, i will also update the original post. Only sh is available to me at the moment. But that is a limitation that only affects my specific situation, answers using other shells are still good answers I think.

– Inbar Rose
Jul 28 at 8:42





@ilkkachu Thanks for the question, i will also update the original post. Only sh is available to me at the moment. But that is a limitation that only affects my specific situation, answers using other shells are still good answers I think.

– Inbar Rose
Jul 28 at 8:42













You may want to look up cpio for this.

– mpez0
Jul 29 at 14:50





You may want to look up cpio for this.

– mpez0
Jul 29 at 14:50










8 Answers
8






active

oldest

votes


















8














Using the output of ls is generally unwise and unsafe - remember that both spaces and newlines and other shell meta-characters are valid characters in a file or directory name. It is possible to work around this problem in many cases, but doing so is usually more effort than just using the right tool for the job (i.e. find).



So, use find instead. For example:



find . -maxdepth 1 -type d ( -name here_is_a_dir -o -name here_is_another_one 
-o -name yet_another_dir ) -exec tar cfz archive.tgz +


This finds any of the matching directories (-type d) in the current directory (.) and uses them as arguments to the tar command. The ( to ) is an expression where each of the sub-expressions are OR-ed together using -o (by default, find's predicates are AND-ed). i.e. it reads as "maxdepth 1 AND type directory AND (dir1 OR dir2 OR dir3)".



Note that without the brackets to force precedence, it would be interpreted as "maxdepth 1 AND type directory AND dir1 OR (dir2 OR dir3)", which would not return the full list of all existing directories. Mostly, it would return either nothing, or only dir3, depending on whether dir1 existed or not.



If you want it to find the sub-directories anywhere underneath the current directory, drop the -maxdepth 1 argument.



If you want the directory matches to be case-insensitive, use -iname instead of -name. Note that the argument to -name or -iname can be a pattern rather than a fixed string - this is useful if the desired directory names are very similar. e.g.



find . -maxdepth 1 -type d -iname 'dir[123]' -exec tar cfz archive.tgz +


The -exec .... works a lot like piping to xargs, but built in to find. In fact, you could use xargs if you wanted to by replacing everything from -exec onwards with -print0 | xargs -0 -r tar cfz archive.tgz. e.g.



find . -maxdepth 1 -type d -iname 'dir[123]' -print0 | 
xargs -0 -r tar cfz archive.tgz


(this uses a NUL character as the output separator, so it's as safe to use with dirnames that contain spaces etc as it is to use -exec. The -r option tells xargs to do nothing if there is no input)






share|improve this answer



























  • This is very good. It may be worth mentioning, for the xargs variant, that -r is a GNU extension (according to the man page).

    – David Conrad
    Jul 28 at 21:12






  • 1





    @DavidConrad that's true. These days, I assume a GNU environment unless explicitly stated otherwise (it is the most common *nix-like userland, so makes a reasonable default). Not all find versions support -print0 either, but you have to go pretty far back in history (paleo-unix :-) to find one that doesn't. BTW, I noticed that busybox has been mentioned in other comments here - man busybox reveals that it supports xargs -r. as does freebsd's version of xargs (a null option. not actually needed, it does that by default. only for compatibilty with GNU).

    – cas
    Jul 29 at 1:29












  • Good to know about busybox. I wouldn't have even mentioned xargs -r except OP mentioned being so limited as to shell.

    – David Conrad
    Jul 29 at 2:39


















7














With zsh:



dirs_to_archive=(some/dir /some/other/dir and/more/dirs)
existing_dirs=($^dirs_to_archive(/N))
if (($#existing_dirs)); then
tar -cf - -- $existing_dirs | xz > file.tar.xz
else
echo >&2 Error: none of the dirs were found
fi


The POSIX equivalent (though note that neither tar nor xz are POSIX commands) would be something like:



# The list of dirs in "$@" (the only array in POSIX sh language)
set -- some/dir /some/other/dir and/more/dirs

for dir do
# remove from the array the elements that are not directories like with
# zsh's / glob qualifier above
[ -d "$dir" ] && [ ! -L "$dir" ] && set -- "$@" "$dir"
shift
done
if [ "$#" -gt 0 ]; then
tar -cf - -- "$@" | xz > file.tar.xz
else
echo >&2 Error: none of the dirs were found
fi





share|improve this answer


































    3














    If you can use bash, then with extended globbing (extglob):



    $ shopt -s extglob; set -x
    $ tar -czf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
    + tar -czf archive.tgz
    tar: no files or directories specified


    And if one or more of those exist:



    $ touch here_is_a_dir yet_another_dir
    + touch here_is_a_dir yet_another_dir
    $ tar -czvf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
    + tar -czvf archive.tgz here_is_a_dir yet_another_dir
    a here_is_a_dir
    a yet_another_dir


    (I have used set -x so you can see the results of the glob expansion.)






    share|improve this answer

























    • that would be very useful, unfortunately bash is not available to me in this environment. But the answer is still correct and gets my +1

      – Inbar Rose
      Jul 28 at 8:11


















    1














    This can be done relatively easily using ls to make a list of existing directories, and then piping through xargs into the tar command.



    solution:



    ls -d here_is_a_dir here_is_another_one yet_another_dir 2> /dev/null | xargs tar -czf archive.tgz



    breakdown:




    • ls -d only list directories


    • here_is_a_dir here_is_another_one yet_another_dir the list of directories to check for


    • 2> /dev/null pipe the stderr to /dev/null so we only get stdout output (no missing dirs)


    • | xargs turns the list of existing directories from the previous command into arguments


    • tar -czf archive.tgz make an archive using the arguments





    share|improve this answer



























    • Note that xargs tries to find out how many arguments it can provide to the given command. Under unfavorable circumstances this could be 1, resulting in tar -czf archive.tgz being started separately for each directory. In that case you would only have the last directory in the archive.

      – Gerald Schneider
      Jul 29 at 13:11


















    0














    One that should work with just POSIX sh (tar.sh):



    #!/bin/sh

    first=1
    for dir in "$@"; do
    if [ "$first" ]; then # this is a bit ugly
    set --
    first=
    fi
    if [ -d "$dir" ]; then
    set -- "$@" "$dir"
    fi
    done
    echo tar -czf archive.tar.gz "$@" # remove that 'echo'


    Test:



    $ mkdir here_is_a_dir yet_another_dir
    $ ./tar.sh here_is_a_dir here_is_another_one yet_another_dir
    tar -czf archive.tar.gz here_is_a_dir yet_another_dir





    share|improve this answer
































      0














      If you have pax, you can use it to filter what gets included in the archive. Pax is mandated by POSIX as a replacement for the historically diverse cpio and tar, but many Unix variants have resisted its adoption, and in particular BusyBox doesn't have it.



      Pax has a file exclusion feature, even though it's rather hidden in the description. You can rename files with -s. If you rename a file to the empty string, it gets excluded. With multiple -s options, for each the first match applies and renaming -s filters are skipped. This way, you can build a series of include/exclude rules, much like with rsync. An include rule in Pax syntax is -s'!REGEX!&!' (rename to itself) and an exclude rule is -s'!REGEX!!' (rename to empty).



      pax -w -x ustar 
      -s'!^./here_is_a_dir$!&!' -s'!^./here_is_a_dir/!&!'
      -s'!^./here_is_another_one$!&!' -s'!^./here_is_another_one/!&!'
      -s'!^./yet_another_dir$!&!' -s'!^./yet_another_dir/!&!'
      . | gzip >archive.tgz


      BSD tar has a similar -s option. On the other hand, GNU tar and BusyBox tar don't have any way to do this include/exclude gymnastics.






      share|improve this answer
































        0














        Simplest is probably



        find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar





        share|improve this answer
































          0














          If your version of tar supports it, create an empty tar file, and append to it as necessary using -r instead of -c



          touch foo.tar

          for d in here_is_a_dir here_is_another_one yet_another_dir; do
          if [ -d "$d" ]; then
          tar -rf foo.tar "$d"
          fi
          done
          gzip foo.tar





          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',
            autoActivateHeartbeat: false,
            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%2f532560%2fhow-to-tar-a-list-of-directories-only-if-they-exist%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            8 Answers
            8






            active

            oldest

            votes








            8 Answers
            8






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            8














            Using the output of ls is generally unwise and unsafe - remember that both spaces and newlines and other shell meta-characters are valid characters in a file or directory name. It is possible to work around this problem in many cases, but doing so is usually more effort than just using the right tool for the job (i.e. find).



            So, use find instead. For example:



            find . -maxdepth 1 -type d ( -name here_is_a_dir -o -name here_is_another_one 
            -o -name yet_another_dir ) -exec tar cfz archive.tgz +


            This finds any of the matching directories (-type d) in the current directory (.) and uses them as arguments to the tar command. The ( to ) is an expression where each of the sub-expressions are OR-ed together using -o (by default, find's predicates are AND-ed). i.e. it reads as "maxdepth 1 AND type directory AND (dir1 OR dir2 OR dir3)".



            Note that without the brackets to force precedence, it would be interpreted as "maxdepth 1 AND type directory AND dir1 OR (dir2 OR dir3)", which would not return the full list of all existing directories. Mostly, it would return either nothing, or only dir3, depending on whether dir1 existed or not.



            If you want it to find the sub-directories anywhere underneath the current directory, drop the -maxdepth 1 argument.



            If you want the directory matches to be case-insensitive, use -iname instead of -name. Note that the argument to -name or -iname can be a pattern rather than a fixed string - this is useful if the desired directory names are very similar. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -exec tar cfz archive.tgz +


            The -exec .... works a lot like piping to xargs, but built in to find. In fact, you could use xargs if you wanted to by replacing everything from -exec onwards with -print0 | xargs -0 -r tar cfz archive.tgz. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -print0 | 
            xargs -0 -r tar cfz archive.tgz


            (this uses a NUL character as the output separator, so it's as safe to use with dirnames that contain spaces etc as it is to use -exec. The -r option tells xargs to do nothing if there is no input)






            share|improve this answer



























            • This is very good. It may be worth mentioning, for the xargs variant, that -r is a GNU extension (according to the man page).

              – David Conrad
              Jul 28 at 21:12






            • 1





              @DavidConrad that's true. These days, I assume a GNU environment unless explicitly stated otherwise (it is the most common *nix-like userland, so makes a reasonable default). Not all find versions support -print0 either, but you have to go pretty far back in history (paleo-unix :-) to find one that doesn't. BTW, I noticed that busybox has been mentioned in other comments here - man busybox reveals that it supports xargs -r. as does freebsd's version of xargs (a null option. not actually needed, it does that by default. only for compatibilty with GNU).

              – cas
              Jul 29 at 1:29












            • Good to know about busybox. I wouldn't have even mentioned xargs -r except OP mentioned being so limited as to shell.

              – David Conrad
              Jul 29 at 2:39















            8














            Using the output of ls is generally unwise and unsafe - remember that both spaces and newlines and other shell meta-characters are valid characters in a file or directory name. It is possible to work around this problem in many cases, but doing so is usually more effort than just using the right tool for the job (i.e. find).



            So, use find instead. For example:



            find . -maxdepth 1 -type d ( -name here_is_a_dir -o -name here_is_another_one 
            -o -name yet_another_dir ) -exec tar cfz archive.tgz +


            This finds any of the matching directories (-type d) in the current directory (.) and uses them as arguments to the tar command. The ( to ) is an expression where each of the sub-expressions are OR-ed together using -o (by default, find's predicates are AND-ed). i.e. it reads as "maxdepth 1 AND type directory AND (dir1 OR dir2 OR dir3)".



            Note that without the brackets to force precedence, it would be interpreted as "maxdepth 1 AND type directory AND dir1 OR (dir2 OR dir3)", which would not return the full list of all existing directories. Mostly, it would return either nothing, or only dir3, depending on whether dir1 existed or not.



            If you want it to find the sub-directories anywhere underneath the current directory, drop the -maxdepth 1 argument.



            If you want the directory matches to be case-insensitive, use -iname instead of -name. Note that the argument to -name or -iname can be a pattern rather than a fixed string - this is useful if the desired directory names are very similar. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -exec tar cfz archive.tgz +


            The -exec .... works a lot like piping to xargs, but built in to find. In fact, you could use xargs if you wanted to by replacing everything from -exec onwards with -print0 | xargs -0 -r tar cfz archive.tgz. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -print0 | 
            xargs -0 -r tar cfz archive.tgz


            (this uses a NUL character as the output separator, so it's as safe to use with dirnames that contain spaces etc as it is to use -exec. The -r option tells xargs to do nothing if there is no input)






            share|improve this answer



























            • This is very good. It may be worth mentioning, for the xargs variant, that -r is a GNU extension (according to the man page).

              – David Conrad
              Jul 28 at 21:12






            • 1





              @DavidConrad that's true. These days, I assume a GNU environment unless explicitly stated otherwise (it is the most common *nix-like userland, so makes a reasonable default). Not all find versions support -print0 either, but you have to go pretty far back in history (paleo-unix :-) to find one that doesn't. BTW, I noticed that busybox has been mentioned in other comments here - man busybox reveals that it supports xargs -r. as does freebsd's version of xargs (a null option. not actually needed, it does that by default. only for compatibilty with GNU).

              – cas
              Jul 29 at 1:29












            • Good to know about busybox. I wouldn't have even mentioned xargs -r except OP mentioned being so limited as to shell.

              – David Conrad
              Jul 29 at 2:39













            8












            8








            8







            Using the output of ls is generally unwise and unsafe - remember that both spaces and newlines and other shell meta-characters are valid characters in a file or directory name. It is possible to work around this problem in many cases, but doing so is usually more effort than just using the right tool for the job (i.e. find).



            So, use find instead. For example:



            find . -maxdepth 1 -type d ( -name here_is_a_dir -o -name here_is_another_one 
            -o -name yet_another_dir ) -exec tar cfz archive.tgz +


            This finds any of the matching directories (-type d) in the current directory (.) and uses them as arguments to the tar command. The ( to ) is an expression where each of the sub-expressions are OR-ed together using -o (by default, find's predicates are AND-ed). i.e. it reads as "maxdepth 1 AND type directory AND (dir1 OR dir2 OR dir3)".



            Note that without the brackets to force precedence, it would be interpreted as "maxdepth 1 AND type directory AND dir1 OR (dir2 OR dir3)", which would not return the full list of all existing directories. Mostly, it would return either nothing, or only dir3, depending on whether dir1 existed or not.



            If you want it to find the sub-directories anywhere underneath the current directory, drop the -maxdepth 1 argument.



            If you want the directory matches to be case-insensitive, use -iname instead of -name. Note that the argument to -name or -iname can be a pattern rather than a fixed string - this is useful if the desired directory names are very similar. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -exec tar cfz archive.tgz +


            The -exec .... works a lot like piping to xargs, but built in to find. In fact, you could use xargs if you wanted to by replacing everything from -exec onwards with -print0 | xargs -0 -r tar cfz archive.tgz. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -print0 | 
            xargs -0 -r tar cfz archive.tgz


            (this uses a NUL character as the output separator, so it's as safe to use with dirnames that contain spaces etc as it is to use -exec. The -r option tells xargs to do nothing if there is no input)






            share|improve this answer















            Using the output of ls is generally unwise and unsafe - remember that both spaces and newlines and other shell meta-characters are valid characters in a file or directory name. It is possible to work around this problem in many cases, but doing so is usually more effort than just using the right tool for the job (i.e. find).



            So, use find instead. For example:



            find . -maxdepth 1 -type d ( -name here_is_a_dir -o -name here_is_another_one 
            -o -name yet_another_dir ) -exec tar cfz archive.tgz +


            This finds any of the matching directories (-type d) in the current directory (.) and uses them as arguments to the tar command. The ( to ) is an expression where each of the sub-expressions are OR-ed together using -o (by default, find's predicates are AND-ed). i.e. it reads as "maxdepth 1 AND type directory AND (dir1 OR dir2 OR dir3)".



            Note that without the brackets to force precedence, it would be interpreted as "maxdepth 1 AND type directory AND dir1 OR (dir2 OR dir3)", which would not return the full list of all existing directories. Mostly, it would return either nothing, or only dir3, depending on whether dir1 existed or not.



            If you want it to find the sub-directories anywhere underneath the current directory, drop the -maxdepth 1 argument.



            If you want the directory matches to be case-insensitive, use -iname instead of -name. Note that the argument to -name or -iname can be a pattern rather than a fixed string - this is useful if the desired directory names are very similar. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -exec tar cfz archive.tgz +


            The -exec .... works a lot like piping to xargs, but built in to find. In fact, you could use xargs if you wanted to by replacing everything from -exec onwards with -print0 | xargs -0 -r tar cfz archive.tgz. e.g.



            find . -maxdepth 1 -type d -iname 'dir[123]' -print0 | 
            xargs -0 -r tar cfz archive.tgz


            (this uses a NUL character as the output separator, so it's as safe to use with dirnames that contain spaces etc as it is to use -exec. The -r option tells xargs to do nothing if there is no input)







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jul 28 at 11:01

























            answered Jul 28 at 10:50









            cascas

            41.1k4 gold badges59 silver badges110 bronze badges




            41.1k4 gold badges59 silver badges110 bronze badges















            • This is very good. It may be worth mentioning, for the xargs variant, that -r is a GNU extension (according to the man page).

              – David Conrad
              Jul 28 at 21:12






            • 1





              @DavidConrad that's true. These days, I assume a GNU environment unless explicitly stated otherwise (it is the most common *nix-like userland, so makes a reasonable default). Not all find versions support -print0 either, but you have to go pretty far back in history (paleo-unix :-) to find one that doesn't. BTW, I noticed that busybox has been mentioned in other comments here - man busybox reveals that it supports xargs -r. as does freebsd's version of xargs (a null option. not actually needed, it does that by default. only for compatibilty with GNU).

              – cas
              Jul 29 at 1:29












            • Good to know about busybox. I wouldn't have even mentioned xargs -r except OP mentioned being so limited as to shell.

              – David Conrad
              Jul 29 at 2:39

















            • This is very good. It may be worth mentioning, for the xargs variant, that -r is a GNU extension (according to the man page).

              – David Conrad
              Jul 28 at 21:12






            • 1





              @DavidConrad that's true. These days, I assume a GNU environment unless explicitly stated otherwise (it is the most common *nix-like userland, so makes a reasonable default). Not all find versions support -print0 either, but you have to go pretty far back in history (paleo-unix :-) to find one that doesn't. BTW, I noticed that busybox has been mentioned in other comments here - man busybox reveals that it supports xargs -r. as does freebsd's version of xargs (a null option. not actually needed, it does that by default. only for compatibilty with GNU).

              – cas
              Jul 29 at 1:29












            • Good to know about busybox. I wouldn't have even mentioned xargs -r except OP mentioned being so limited as to shell.

              – David Conrad
              Jul 29 at 2:39
















            This is very good. It may be worth mentioning, for the xargs variant, that -r is a GNU extension (according to the man page).

            – David Conrad
            Jul 28 at 21:12





            This is very good. It may be worth mentioning, for the xargs variant, that -r is a GNU extension (according to the man page).

            – David Conrad
            Jul 28 at 21:12




            1




            1





            @DavidConrad that's true. These days, I assume a GNU environment unless explicitly stated otherwise (it is the most common *nix-like userland, so makes a reasonable default). Not all find versions support -print0 either, but you have to go pretty far back in history (paleo-unix :-) to find one that doesn't. BTW, I noticed that busybox has been mentioned in other comments here - man busybox reveals that it supports xargs -r. as does freebsd's version of xargs (a null option. not actually needed, it does that by default. only for compatibilty with GNU).

            – cas
            Jul 29 at 1:29






            @DavidConrad that's true. These days, I assume a GNU environment unless explicitly stated otherwise (it is the most common *nix-like userland, so makes a reasonable default). Not all find versions support -print0 either, but you have to go pretty far back in history (paleo-unix :-) to find one that doesn't. BTW, I noticed that busybox has been mentioned in other comments here - man busybox reveals that it supports xargs -r. as does freebsd's version of xargs (a null option. not actually needed, it does that by default. only for compatibilty with GNU).

            – cas
            Jul 29 at 1:29














            Good to know about busybox. I wouldn't have even mentioned xargs -r except OP mentioned being so limited as to shell.

            – David Conrad
            Jul 29 at 2:39





            Good to know about busybox. I wouldn't have even mentioned xargs -r except OP mentioned being so limited as to shell.

            – David Conrad
            Jul 29 at 2:39













            7














            With zsh:



            dirs_to_archive=(some/dir /some/other/dir and/more/dirs)
            existing_dirs=($^dirs_to_archive(/N))
            if (($#existing_dirs)); then
            tar -cf - -- $existing_dirs | xz > file.tar.xz
            else
            echo >&2 Error: none of the dirs were found
            fi


            The POSIX equivalent (though note that neither tar nor xz are POSIX commands) would be something like:



            # The list of dirs in "$@" (the only array in POSIX sh language)
            set -- some/dir /some/other/dir and/more/dirs

            for dir do
            # remove from the array the elements that are not directories like with
            # zsh's / glob qualifier above
            [ -d "$dir" ] && [ ! -L "$dir" ] && set -- "$@" "$dir"
            shift
            done
            if [ "$#" -gt 0 ]; then
            tar -cf - -- "$@" | xz > file.tar.xz
            else
            echo >&2 Error: none of the dirs were found
            fi





            share|improve this answer































              7














              With zsh:



              dirs_to_archive=(some/dir /some/other/dir and/more/dirs)
              existing_dirs=($^dirs_to_archive(/N))
              if (($#existing_dirs)); then
              tar -cf - -- $existing_dirs | xz > file.tar.xz
              else
              echo >&2 Error: none of the dirs were found
              fi


              The POSIX equivalent (though note that neither tar nor xz are POSIX commands) would be something like:



              # The list of dirs in "$@" (the only array in POSIX sh language)
              set -- some/dir /some/other/dir and/more/dirs

              for dir do
              # remove from the array the elements that are not directories like with
              # zsh's / glob qualifier above
              [ -d "$dir" ] && [ ! -L "$dir" ] && set -- "$@" "$dir"
              shift
              done
              if [ "$#" -gt 0 ]; then
              tar -cf - -- "$@" | xz > file.tar.xz
              else
              echo >&2 Error: none of the dirs were found
              fi





              share|improve this answer





























                7












                7








                7







                With zsh:



                dirs_to_archive=(some/dir /some/other/dir and/more/dirs)
                existing_dirs=($^dirs_to_archive(/N))
                if (($#existing_dirs)); then
                tar -cf - -- $existing_dirs | xz > file.tar.xz
                else
                echo >&2 Error: none of the dirs were found
                fi


                The POSIX equivalent (though note that neither tar nor xz are POSIX commands) would be something like:



                # The list of dirs in "$@" (the only array in POSIX sh language)
                set -- some/dir /some/other/dir and/more/dirs

                for dir do
                # remove from the array the elements that are not directories like with
                # zsh's / glob qualifier above
                [ -d "$dir" ] && [ ! -L "$dir" ] && set -- "$@" "$dir"
                shift
                done
                if [ "$#" -gt 0 ]; then
                tar -cf - -- "$@" | xz > file.tar.xz
                else
                echo >&2 Error: none of the dirs were found
                fi





                share|improve this answer















                With zsh:



                dirs_to_archive=(some/dir /some/other/dir and/more/dirs)
                existing_dirs=($^dirs_to_archive(/N))
                if (($#existing_dirs)); then
                tar -cf - -- $existing_dirs | xz > file.tar.xz
                else
                echo >&2 Error: none of the dirs were found
                fi


                The POSIX equivalent (though note that neither tar nor xz are POSIX commands) would be something like:



                # The list of dirs in "$@" (the only array in POSIX sh language)
                set -- some/dir /some/other/dir and/more/dirs

                for dir do
                # remove from the array the elements that are not directories like with
                # zsh's / glob qualifier above
                [ -d "$dir" ] && [ ! -L "$dir" ] && set -- "$@" "$dir"
                shift
                done
                if [ "$#" -gt 0 ]; then
                tar -cf - -- "$@" | xz > file.tar.xz
                else
                echo >&2 Error: none of the dirs were found
                fi






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jul 28 at 11:18

























                answered Jul 28 at 9:04









                Stéphane ChazelasStéphane Chazelas

                328k57 gold badges638 silver badges1006 bronze badges




                328k57 gold badges638 silver badges1006 bronze badges
























                    3














                    If you can use bash, then with extended globbing (extglob):



                    $ shopt -s extglob; set -x
                    $ tar -czf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czf archive.tgz
                    tar: no files or directories specified


                    And if one or more of those exist:



                    $ touch here_is_a_dir yet_another_dir
                    + touch here_is_a_dir yet_another_dir
                    $ tar -czvf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czvf archive.tgz here_is_a_dir yet_another_dir
                    a here_is_a_dir
                    a yet_another_dir


                    (I have used set -x so you can see the results of the glob expansion.)






                    share|improve this answer

























                    • that would be very useful, unfortunately bash is not available to me in this environment. But the answer is still correct and gets my +1

                      – Inbar Rose
                      Jul 28 at 8:11















                    3














                    If you can use bash, then with extended globbing (extglob):



                    $ shopt -s extglob; set -x
                    $ tar -czf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czf archive.tgz
                    tar: no files or directories specified


                    And if one or more of those exist:



                    $ touch here_is_a_dir yet_another_dir
                    + touch here_is_a_dir yet_another_dir
                    $ tar -czvf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czvf archive.tgz here_is_a_dir yet_another_dir
                    a here_is_a_dir
                    a yet_another_dir


                    (I have used set -x so you can see the results of the glob expansion.)






                    share|improve this answer

























                    • that would be very useful, unfortunately bash is not available to me in this environment. But the answer is still correct and gets my +1

                      – Inbar Rose
                      Jul 28 at 8:11













                    3












                    3








                    3







                    If you can use bash, then with extended globbing (extglob):



                    $ shopt -s extglob; set -x
                    $ tar -czf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czf archive.tgz
                    tar: no files or directories specified


                    And if one or more of those exist:



                    $ touch here_is_a_dir yet_another_dir
                    + touch here_is_a_dir yet_another_dir
                    $ tar -czvf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czvf archive.tgz here_is_a_dir yet_another_dir
                    a here_is_a_dir
                    a yet_another_dir


                    (I have used set -x so you can see the results of the glob expansion.)






                    share|improve this answer













                    If you can use bash, then with extended globbing (extglob):



                    $ shopt -s extglob; set -x
                    $ tar -czf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czf archive.tgz
                    tar: no files or directories specified


                    And if one or more of those exist:



                    $ touch here_is_a_dir yet_another_dir
                    + touch here_is_a_dir yet_another_dir
                    $ tar -czvf archive.tgz *(here_is_a_dir|here_is_another_one|yet_another_dir)
                    + tar -czvf archive.tgz here_is_a_dir yet_another_dir
                    a here_is_a_dir
                    a yet_another_dir


                    (I have used set -x so you can see the results of the glob expansion.)







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Jul 28 at 8:08









                    murumuru

                    43.5k5 gold badges108 silver badges181 bronze badges




                    43.5k5 gold badges108 silver badges181 bronze badges















                    • that would be very useful, unfortunately bash is not available to me in this environment. But the answer is still correct and gets my +1

                      – Inbar Rose
                      Jul 28 at 8:11

















                    • that would be very useful, unfortunately bash is not available to me in this environment. But the answer is still correct and gets my +1

                      – Inbar Rose
                      Jul 28 at 8:11
















                    that would be very useful, unfortunately bash is not available to me in this environment. But the answer is still correct and gets my +1

                    – Inbar Rose
                    Jul 28 at 8:11





                    that would be very useful, unfortunately bash is not available to me in this environment. But the answer is still correct and gets my +1

                    – Inbar Rose
                    Jul 28 at 8:11











                    1














                    This can be done relatively easily using ls to make a list of existing directories, and then piping through xargs into the tar command.



                    solution:



                    ls -d here_is_a_dir here_is_another_one yet_another_dir 2> /dev/null | xargs tar -czf archive.tgz



                    breakdown:




                    • ls -d only list directories


                    • here_is_a_dir here_is_another_one yet_another_dir the list of directories to check for


                    • 2> /dev/null pipe the stderr to /dev/null so we only get stdout output (no missing dirs)


                    • | xargs turns the list of existing directories from the previous command into arguments


                    • tar -czf archive.tgz make an archive using the arguments





                    share|improve this answer



























                    • Note that xargs tries to find out how many arguments it can provide to the given command. Under unfavorable circumstances this could be 1, resulting in tar -czf archive.tgz being started separately for each directory. In that case you would only have the last directory in the archive.

                      – Gerald Schneider
                      Jul 29 at 13:11















                    1














                    This can be done relatively easily using ls to make a list of existing directories, and then piping through xargs into the tar command.



                    solution:



                    ls -d here_is_a_dir here_is_another_one yet_another_dir 2> /dev/null | xargs tar -czf archive.tgz



                    breakdown:




                    • ls -d only list directories


                    • here_is_a_dir here_is_another_one yet_another_dir the list of directories to check for


                    • 2> /dev/null pipe the stderr to /dev/null so we only get stdout output (no missing dirs)


                    • | xargs turns the list of existing directories from the previous command into arguments


                    • tar -czf archive.tgz make an archive using the arguments





                    share|improve this answer



























                    • Note that xargs tries to find out how many arguments it can provide to the given command. Under unfavorable circumstances this could be 1, resulting in tar -czf archive.tgz being started separately for each directory. In that case you would only have the last directory in the archive.

                      – Gerald Schneider
                      Jul 29 at 13:11













                    1












                    1








                    1







                    This can be done relatively easily using ls to make a list of existing directories, and then piping through xargs into the tar command.



                    solution:



                    ls -d here_is_a_dir here_is_another_one yet_another_dir 2> /dev/null | xargs tar -czf archive.tgz



                    breakdown:




                    • ls -d only list directories


                    • here_is_a_dir here_is_another_one yet_another_dir the list of directories to check for


                    • 2> /dev/null pipe the stderr to /dev/null so we only get stdout output (no missing dirs)


                    • | xargs turns the list of existing directories from the previous command into arguments


                    • tar -czf archive.tgz make an archive using the arguments





                    share|improve this answer















                    This can be done relatively easily using ls to make a list of existing directories, and then piping through xargs into the tar command.



                    solution:



                    ls -d here_is_a_dir here_is_another_one yet_another_dir 2> /dev/null | xargs tar -czf archive.tgz



                    breakdown:




                    • ls -d only list directories


                    • here_is_a_dir here_is_another_one yet_another_dir the list of directories to check for


                    • 2> /dev/null pipe the stderr to /dev/null so we only get stdout output (no missing dirs)


                    • | xargs turns the list of existing directories from the previous command into arguments


                    • tar -czf archive.tgz make an archive using the arguments






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jul 28 at 8:04

























                    answered Jul 28 at 7:31









                    Inbar RoseInbar Rose

                    1461 silver badge6 bronze badges




                    1461 silver badge6 bronze badges















                    • Note that xargs tries to find out how many arguments it can provide to the given command. Under unfavorable circumstances this could be 1, resulting in tar -czf archive.tgz being started separately for each directory. In that case you would only have the last directory in the archive.

                      – Gerald Schneider
                      Jul 29 at 13:11

















                    • Note that xargs tries to find out how many arguments it can provide to the given command. Under unfavorable circumstances this could be 1, resulting in tar -czf archive.tgz being started separately for each directory. In that case you would only have the last directory in the archive.

                      – Gerald Schneider
                      Jul 29 at 13:11
















                    Note that xargs tries to find out how many arguments it can provide to the given command. Under unfavorable circumstances this could be 1, resulting in tar -czf archive.tgz being started separately for each directory. In that case you would only have the last directory in the archive.

                    – Gerald Schneider
                    Jul 29 at 13:11





                    Note that xargs tries to find out how many arguments it can provide to the given command. Under unfavorable circumstances this could be 1, resulting in tar -czf archive.tgz being started separately for each directory. In that case you would only have the last directory in the archive.

                    – Gerald Schneider
                    Jul 29 at 13:11











                    0














                    One that should work with just POSIX sh (tar.sh):



                    #!/bin/sh

                    first=1
                    for dir in "$@"; do
                    if [ "$first" ]; then # this is a bit ugly
                    set --
                    first=
                    fi
                    if [ -d "$dir" ]; then
                    set -- "$@" "$dir"
                    fi
                    done
                    echo tar -czf archive.tar.gz "$@" # remove that 'echo'


                    Test:



                    $ mkdir here_is_a_dir yet_another_dir
                    $ ./tar.sh here_is_a_dir here_is_another_one yet_another_dir
                    tar -czf archive.tar.gz here_is_a_dir yet_another_dir





                    share|improve this answer





























                      0














                      One that should work with just POSIX sh (tar.sh):



                      #!/bin/sh

                      first=1
                      for dir in "$@"; do
                      if [ "$first" ]; then # this is a bit ugly
                      set --
                      first=
                      fi
                      if [ -d "$dir" ]; then
                      set -- "$@" "$dir"
                      fi
                      done
                      echo tar -czf archive.tar.gz "$@" # remove that 'echo'


                      Test:



                      $ mkdir here_is_a_dir yet_another_dir
                      $ ./tar.sh here_is_a_dir here_is_another_one yet_another_dir
                      tar -czf archive.tar.gz here_is_a_dir yet_another_dir





                      share|improve this answer



























                        0












                        0








                        0







                        One that should work with just POSIX sh (tar.sh):



                        #!/bin/sh

                        first=1
                        for dir in "$@"; do
                        if [ "$first" ]; then # this is a bit ugly
                        set --
                        first=
                        fi
                        if [ -d "$dir" ]; then
                        set -- "$@" "$dir"
                        fi
                        done
                        echo tar -czf archive.tar.gz "$@" # remove that 'echo'


                        Test:



                        $ mkdir here_is_a_dir yet_another_dir
                        $ ./tar.sh here_is_a_dir here_is_another_one yet_another_dir
                        tar -czf archive.tar.gz here_is_a_dir yet_another_dir





                        share|improve this answer













                        One that should work with just POSIX sh (tar.sh):



                        #!/bin/sh

                        first=1
                        for dir in "$@"; do
                        if [ "$first" ]; then # this is a bit ugly
                        set --
                        first=
                        fi
                        if [ -d "$dir" ]; then
                        set -- "$@" "$dir"
                        fi
                        done
                        echo tar -czf archive.tar.gz "$@" # remove that 'echo'


                        Test:



                        $ mkdir here_is_a_dir yet_another_dir
                        $ ./tar.sh here_is_a_dir here_is_another_one yet_another_dir
                        tar -czf archive.tar.gz here_is_a_dir yet_another_dir






                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Jul 28 at 15:59









                        ilkkachuilkkachu

                        66.7k10 gold badges111 silver badges193 bronze badges




                        66.7k10 gold badges111 silver badges193 bronze badges
























                            0














                            If you have pax, you can use it to filter what gets included in the archive. Pax is mandated by POSIX as a replacement for the historically diverse cpio and tar, but many Unix variants have resisted its adoption, and in particular BusyBox doesn't have it.



                            Pax has a file exclusion feature, even though it's rather hidden in the description. You can rename files with -s. If you rename a file to the empty string, it gets excluded. With multiple -s options, for each the first match applies and renaming -s filters are skipped. This way, you can build a series of include/exclude rules, much like with rsync. An include rule in Pax syntax is -s'!REGEX!&!' (rename to itself) and an exclude rule is -s'!REGEX!!' (rename to empty).



                            pax -w -x ustar 
                            -s'!^./here_is_a_dir$!&!' -s'!^./here_is_a_dir/!&!'
                            -s'!^./here_is_another_one$!&!' -s'!^./here_is_another_one/!&!'
                            -s'!^./yet_another_dir$!&!' -s'!^./yet_another_dir/!&!'
                            . | gzip >archive.tgz


                            BSD tar has a similar -s option. On the other hand, GNU tar and BusyBox tar don't have any way to do this include/exclude gymnastics.






                            share|improve this answer





























                              0














                              If you have pax, you can use it to filter what gets included in the archive. Pax is mandated by POSIX as a replacement for the historically diverse cpio and tar, but many Unix variants have resisted its adoption, and in particular BusyBox doesn't have it.



                              Pax has a file exclusion feature, even though it's rather hidden in the description. You can rename files with -s. If you rename a file to the empty string, it gets excluded. With multiple -s options, for each the first match applies and renaming -s filters are skipped. This way, you can build a series of include/exclude rules, much like with rsync. An include rule in Pax syntax is -s'!REGEX!&!' (rename to itself) and an exclude rule is -s'!REGEX!!' (rename to empty).



                              pax -w -x ustar 
                              -s'!^./here_is_a_dir$!&!' -s'!^./here_is_a_dir/!&!'
                              -s'!^./here_is_another_one$!&!' -s'!^./here_is_another_one/!&!'
                              -s'!^./yet_another_dir$!&!' -s'!^./yet_another_dir/!&!'
                              . | gzip >archive.tgz


                              BSD tar has a similar -s option. On the other hand, GNU tar and BusyBox tar don't have any way to do this include/exclude gymnastics.






                              share|improve this answer



























                                0












                                0








                                0







                                If you have pax, you can use it to filter what gets included in the archive. Pax is mandated by POSIX as a replacement for the historically diverse cpio and tar, but many Unix variants have resisted its adoption, and in particular BusyBox doesn't have it.



                                Pax has a file exclusion feature, even though it's rather hidden in the description. You can rename files with -s. If you rename a file to the empty string, it gets excluded. With multiple -s options, for each the first match applies and renaming -s filters are skipped. This way, you can build a series of include/exclude rules, much like with rsync. An include rule in Pax syntax is -s'!REGEX!&!' (rename to itself) and an exclude rule is -s'!REGEX!!' (rename to empty).



                                pax -w -x ustar 
                                -s'!^./here_is_a_dir$!&!' -s'!^./here_is_a_dir/!&!'
                                -s'!^./here_is_another_one$!&!' -s'!^./here_is_another_one/!&!'
                                -s'!^./yet_another_dir$!&!' -s'!^./yet_another_dir/!&!'
                                . | gzip >archive.tgz


                                BSD tar has a similar -s option. On the other hand, GNU tar and BusyBox tar don't have any way to do this include/exclude gymnastics.






                                share|improve this answer













                                If you have pax, you can use it to filter what gets included in the archive. Pax is mandated by POSIX as a replacement for the historically diverse cpio and tar, but many Unix variants have resisted its adoption, and in particular BusyBox doesn't have it.



                                Pax has a file exclusion feature, even though it's rather hidden in the description. You can rename files with -s. If you rename a file to the empty string, it gets excluded. With multiple -s options, for each the first match applies and renaming -s filters are skipped. This way, you can build a series of include/exclude rules, much like with rsync. An include rule in Pax syntax is -s'!REGEX!&!' (rename to itself) and an exclude rule is -s'!REGEX!!' (rename to empty).



                                pax -w -x ustar 
                                -s'!^./here_is_a_dir$!&!' -s'!^./here_is_a_dir/!&!'
                                -s'!^./here_is_another_one$!&!' -s'!^./here_is_another_one/!&!'
                                -s'!^./yet_another_dir$!&!' -s'!^./yet_another_dir/!&!'
                                . | gzip >archive.tgz


                                BSD tar has a similar -s option. On the other hand, GNU tar and BusyBox tar don't have any way to do this include/exclude gymnastics.







                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Jul 28 at 21:54









                                GillesGilles

                                568k136 gold badges1168 silver badges1682 bronze badges




                                568k136 gold badges1168 silver badges1682 bronze badges
























                                    0














                                    Simplest is probably



                                    find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar





                                    share|improve this answer





























                                      0














                                      Simplest is probably



                                      find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar





                                      share|improve this answer



























                                        0












                                        0








                                        0







                                        Simplest is probably



                                        find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar





                                        share|improve this answer













                                        Simplest is probably



                                        find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Jul 29 at 0:00









                                        jthilljthill

                                        2,3738 silver badges15 bronze badges




                                        2,3738 silver badges15 bronze badges
























                                            0














                                            If your version of tar supports it, create an empty tar file, and append to it as necessary using -r instead of -c



                                            touch foo.tar

                                            for d in here_is_a_dir here_is_another_one yet_another_dir; do
                                            if [ -d "$d" ]; then
                                            tar -rf foo.tar "$d"
                                            fi
                                            done
                                            gzip foo.tar





                                            share|improve this answer





























                                              0














                                              If your version of tar supports it, create an empty tar file, and append to it as necessary using -r instead of -c



                                              touch foo.tar

                                              for d in here_is_a_dir here_is_another_one yet_another_dir; do
                                              if [ -d "$d" ]; then
                                              tar -rf foo.tar "$d"
                                              fi
                                              done
                                              gzip foo.tar





                                              share|improve this answer



























                                                0












                                                0








                                                0







                                                If your version of tar supports it, create an empty tar file, and append to it as necessary using -r instead of -c



                                                touch foo.tar

                                                for d in here_is_a_dir here_is_another_one yet_another_dir; do
                                                if [ -d "$d" ]; then
                                                tar -rf foo.tar "$d"
                                                fi
                                                done
                                                gzip foo.tar





                                                share|improve this answer













                                                If your version of tar supports it, create an empty tar file, and append to it as necessary using -r instead of -c



                                                touch foo.tar

                                                for d in here_is_a_dir here_is_another_one yet_another_dir; do
                                                if [ -d "$d" ]; then
                                                tar -rf foo.tar "$d"
                                                fi
                                                done
                                                gzip foo.tar






                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Jul 29 at 14:44









                                                chepnerchepner

                                                5,53515 silver badges24 bronze badges




                                                5,53515 silver badges24 bronze badges






























                                                    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.




                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function ()
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f532560%2fhow-to-tar-a-list-of-directories-only-if-they-exist%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

                                                    Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

                                                    Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

                                                    Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form