Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to get a regexp (in ksh) to identify files with only the following extensions: tgz, tar.gz, TGZ and TAR.GZ. I tried several but can't get them to work. I'm using this regexp to select only files files with those extensions to do some work with them:

if [ -f $myregexp ]; then
share|improve this question
up vote 1 down vote accepted

[ -f "$myregexp" ] or [[ -f $myregexp ]] tests if there's a file called exactly $myregexp. (Note that with the single brackets, you need the double quotes.)

If you want to test for the existence of files matching a glob pattern, there's no direct way. You have to do it in two steps: first generate the list of matches, then test if that list is empty.

a=( ~(Ni)*.@(tgz|tar.gz) )
if [[ ${#a} -ne 0 ]]; then …

This uses a number of ksh-specific features:

  • the ~(N) prefix to generate an empty list if there is no match;
  • the ~(i) prefix to do case-insensitive matching;
  • the @(foo|bar) glob syntax to match foo or bar

Here's a bash equivalent. In bash, you get case empty expansion for non-matching globs and case insensitivity from options; extglob is for the @(foo|bar) syntax and other ksh glob extensions.

shopt -s nocaseglob nullglob extglob
a=( *.@(tgz|tar.gz) )
if [[ ${#a} -ne 0 ]]; then …

Here's a zsh equivalent. The extended_glob option is needed for the (#i) prefix for a case-insensitive match. The (N) glob qualifier indicates empty expansion for non-matching globs.

setopt extended_glob
a=( (#i)*.(tgz|tar.gz)(N) )
if [[ ${#a} -ne 0 ]]; then …
share|improve this answer

You example doesn't give any clue about what the source you are comparing is. If you want to list files in the current directory you can just string some globs together like this:

for file in *.tgz *.tar.gz *.TGZ *.TAR.GZ; do
    echo $file

If you want to test a file name in a string against a partern, try this:

if [[ ( $file =~ .*\.(tgz|TGZ|tar\.gz|TAR\.GZ) ) ]]; then
    echo $file

Or you can use a case statement:

case $file in
        echo $file
share|improve this answer

You can even do case-insensitive matching with mere glob expressions:

for f in *.[Tt][Gg][Zz] *.[Tt][Aa][Rr].[Gg][Zz]; do
   echo $f
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.