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;
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
add a comment |
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
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. Onlysh
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 upcpio
for this.
– mpez0
Jul 29 at 14:50
add a comment |
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
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
shell-script shell ls tar
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. Onlysh
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 upcpio
for this.
– mpez0
Jul 29 at 14:50
add a comment |
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. Onlysh
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 upcpio
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
add a comment |
8 Answers
8
active
oldest
votes
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)
This is very good. It may be worth mentioning, for thexargs
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 allfind
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 thatbusybox
has been mentioned in other comments here -man busybox
reveals that it supportsxargs -r
. as does freebsd's version ofxargs
(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
add a comment |
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
add a comment |
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.)
that would be very useful, unfortunatelybash
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
add a comment |
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 directorieshere_is_a_dir here_is_another_one yet_another_dir
the list of directories to check for2> /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 argumentstar -czf archive.tgz
make an archive using the arguments
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 intar -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
add a comment |
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
add a comment |
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.
add a comment |
Simplest is probably
find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar
add a comment |
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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)
This is very good. It may be worth mentioning, for thexargs
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 allfind
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 thatbusybox
has been mentioned in other comments here -man busybox
reveals that it supportsxargs -r
. as does freebsd's version ofxargs
(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
add a comment |
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)
This is very good. It may be worth mentioning, for thexargs
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 allfind
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 thatbusybox
has been mentioned in other comments here -man busybox
reveals that it supportsxargs -r
. as does freebsd's version ofxargs
(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
add a comment |
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)
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)
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 thexargs
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 allfind
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 thatbusybox
has been mentioned in other comments here -man busybox
reveals that it supportsxargs -r
. as does freebsd's version ofxargs
(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
add a comment |
This is very good. It may be worth mentioning, for thexargs
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 allfind
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 thatbusybox
has been mentioned in other comments here -man busybox
reveals that it supportsxargs -r
. as does freebsd's version ofxargs
(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
add a comment |
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
add a comment |
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
add a comment |
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
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
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
add a comment |
add a comment |
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.)
that would be very useful, unfortunatelybash
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
add a comment |
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.)
that would be very useful, unfortunatelybash
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
add a comment |
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.)
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.)
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, unfortunatelybash
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
add a comment |
that would be very useful, unfortunatelybash
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
add a comment |
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 directorieshere_is_a_dir here_is_another_one yet_another_dir
the list of directories to check for2> /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 argumentstar -czf archive.tgz
make an archive using the arguments
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 intar -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
add a comment |
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 directorieshere_is_a_dir here_is_another_one yet_another_dir
the list of directories to check for2> /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 argumentstar -czf archive.tgz
make an archive using the arguments
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 intar -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
add a comment |
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 directorieshere_is_a_dir here_is_another_one yet_another_dir
the list of directories to check for2> /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 argumentstar -czf archive.tgz
make an archive using the arguments
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 directorieshere_is_a_dir here_is_another_one yet_another_dir
the list of directories to check for2> /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 argumentstar -czf archive.tgz
make an archive using the arguments
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 intar -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
add a comment |
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 intar -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
add a comment |
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
add a comment |
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
add a comment |
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
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
answered Jul 28 at 15:59
ilkkachuilkkachu
66.7k10 gold badges111 silver badges193 bronze badges
66.7k10 gold badges111 silver badges193 bronze badges
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Jul 28 at 21:54
GillesGilles
568k136 gold badges1168 silver badges1682 bronze badges
568k136 gold badges1168 silver badges1682 bronze badges
add a comment |
add a comment |
Simplest is probably
find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar
add a comment |
Simplest is probably
find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar
add a comment |
Simplest is probably
find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar
Simplest is probably
find adir anotherdir yadir -maxdepth 0 2>&- | tar Tcf - my.tar
answered Jul 29 at 0:00
jthilljthill
2,3738 silver badges15 bronze badges
2,3738 silver badges15 bronze badges
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
answered Jul 29 at 14:44
chepnerchepner
5,53515 silver badges24 bronze badges
5,53515 silver badges24 bronze badges
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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