untar a directory of *.tgz files using a wildcard
Solution 1
You could always do:
ls *.tgz | grep -v Broad_hapmap3_r2_Affy6_cels_excluded.tgz | xargs -n1 tar zxvf
But I suspect somone will post a cleaner way do do this directly from the bash shell without needing a grep in there.
Solution 2
In zsh:
setopt extended_glob
for z in *.tgz~Broad_hapmap3_r2_Affy6_cels_excluded.tgz; do tar xzf $z; done
Another possibility in zsh:
setopt extended_glob
zargs -n 1 -- *.tgz~Broad_hapmap3_r2_Affy6_cels_excluded.tgz -- tar xzf
In ksh (but not bash or zsh as they don't support and patterns):
for z in @(*.tgz&!(Broad_hapmap3_r2_Affy6_cels_excluded.tgz); do tar xzf "$z"; done
Another way in ksh:
( FIGNORE=Broad_hapmap3_r2_Affy6_cels_excluded.tgz;
for z in *.tgz; do tar xzf "$z"; done )
In bash:
( GLOB_IGNORE=Broad_hapmap3_r2_Affy6_cels_excluded.tgz;
for z in *.tgz; do tar xzf "$z"; done )
In any shell:
for z in *.tgz; do
[ "$z" = Broad_hapmap3_r2_Affy6_cels_excluded.tgz ] || tar xzf "$z"
done
Yet another hackish way:
mv Broad_hapmap3_r2_Affy6_cels_excluded.tgz Broad_hapmap3_r2_Affy6_cels_excluded.tgz.not
for z in *.tgz; do tar xzf "$z"; done
mv Broad_hapmap3_r2_Affy6_cels_excluded.tgz.not Broad_hapmap3_r2_Affy6_cels_excluded.tgz
If you also want to act on files in subdirectories, find is the natural tool to turn to. The recursive examples below exclude files named Broad_hapmap3_r2_Affy6_cels_excluded.tgz
in any subdirectory.
find . -name '*.tgz' -type f \
\! -name Broad_hapmap3_r2_Affy6_cels_excluded.tgz \
-exec tar xzf {} \;
For a recursive traversal in zsh or bash ≥4, you can use **
in patterns. In zsh:
setopt extended_glob
zargs -n 1 -- **/*.tgz~**/Broad_hapmap3_r2_Affy6_cels_excluded.tgz -- tar xzf
In bash ≥4:
shopt -s globstar
( GLOB_IGNORE=Broad_hapmap3_r2_Affy6_cels_excluded.tgz;
for z in **/*.tgz; do tar xzf "$z"; done )
You can even use find if you don't want a recursive traversal, though it's not the most convenient way then.
find *.tgz -type f \
\! -name Broad_hapmap3_r2_Affy6_cels_excluded.tgz \
-exec tar xzf {} \;
Solution 3
For one-off things like this, I'd just brute-force it:
for f in *.tgz; do
[[ "$f" != "Broad_hapmap3_r2_Affy6_cels_excluded.tgz" ]] && tar zxvf "$f"
done
Related videos on Youtube
Alen Milakovic
Updated on September 17, 2022Comments
-
Alen Milakovic over 1 year
I've got a directory that looks like
$ ls Broad_hapmap3_r2_Affy6_cels_excluded.tgz DINGO.tgz GIGAS.tgz index.html IONIC.tgz passing_cels_sample_map.txt SCALE.tgz CHEAP.tgz EPODE.tgz HOMOS.tgz index.html?C=M;O=A LOVED.tgz PICUL.tgz SHELF.tgz CORER.tgz excluded_cels_md5.txt HUFFS.tgz index.html?C=N;O=D NIGHS.tgz POSIT.tgz SLOTH.tgz CUPID.tgz excluded_cels_sample_map.txt HUSKS.tgz index.html?C=S;O=A passing_cels_md5.txt SAKES.tgz TESLA.tgz
I want to unzip all the files that match the extension *.tgz with a single command, except Broad_hapmap3_r2_Affy6_cels_excluded.tgz.
I can do
ls *.tgz | xargs -n1 tar zxvf
for all the *tgz files, but what's a good way to exclude a subset of them? From reading online maybe find is indicated in this situation, but it seems like overkill. Thank in advance.
Addendum: I'd also be interested in alternative methods to the question without excluding files.
-
Admin about 13 yearsThanks to everyone for their answers. I'm sorry that I can only accept one. :-)
-
-
Steven D about 13 yearsIn general, you want to avoid parsing the output of
ls
when possible. -
Alen Milakovic about 13 years@Steven: Sorry, don't follow. Can you elaborate?
-
Steven D about 13 yearsWhen you parse the output of
ls
you can run into a lot of problems if you encounter filenames with special characters. See the following for a better explanation: mywiki.wooledge.org/ParsingLs -
Alen Milakovic about 13 years@Steven: Thanks for the link. The referenced article mentions newlines, but now that I think about it, in Windows world for example, they like filenames with spaces in them, and try to export it elsewhere, and that would by itself mess up the oneliner here, I think. What would you prefer as an alternative? find?
-
Steven D about 13 yearsI would use
find
for certain complicated cases and glenn jackman's answer in most easy cases. I wouldn't be surprised if there was some magical shell globbing incantation possible with ZSH or Bash 4. -
Steven D about 13 yearsI think you may have reversed the order of the filenames in your last example. That, or I'm missing something obvious.
-
Alen Milakovic about 13 years@Steven: Thank you for your informative comments.
-
Alen Milakovic about 13 years@Gilles: Thanks, that's quite a variety of approaches! But you forgot to include an approach using find. :-)
-
Gilles 'SO- stop being evil' about 13 years@Steven: fixed. @Faheem: done.
-
Alen Milakovic about 13 years@Gilles: fyi, if you put two @user in the same comment, only the first is notified. See item 7 in meta.stackoverflow.com/questions/43019/…
-
Gilles 'SO- stop being evil' about 13 years@Faheem: I've read that. I was counting on your being notified of my edit.
-
Alen Milakovic about 13 years@Gilles: Ok. Just trying to be helpful. So, do all your solutions work for arbitary filenames? Ie. do they avoid the problem mentioned by Steven above?
-
Gilles 'SO- stop being evil' about 13 years@Faheem: Above what? Do you mean in If you mean in his comments to bdk's answer, the problems are due to the use of
ls
. All the commands in my answer work with arbitrary file names. Be sure to use double quotes everywhere I've used them. If you generalize to commands other thantar
, you'll need to add--
before"$z"
or{}
in some places, but here the file name is an argument totar
's-f
option, not directly to thetar
command, so you don't need and cannot use--
. -
Alen Milakovic about 13 years@Gilles: yes, I meant in Steven's comments in bdk's answer. Thanks.