Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm trying to create a shell script which receive as first parameter of a path to a folder which I would like to compress all files using gzip without overwrite the .gz files that already exist in this folder.

I don't know for which reason this script is not working properly:

#!/bin/bash
FOLDER=$1

cd $FOLDER
for f in *.*; do
  if [ ! -f "$f.gz" ]; then
    echo "Compressing $f file..";
    gzip $f
  else
    echo "Not overwriting $f.gz";
  fi
done

Sometime it gets confused about if the file is a .gz file and don't compress it.

share|improve this question
    
Small note: quotation is needed to handle spaces and other special characters in filenames, i.e. cd "$FOLDER" and gzip "$f". –  Daniel Andersson Feb 20 '13 at 13:10
add comment

1 Answer

up vote 2 down vote accepted

Your criteria are wrong. *.* will return all files with extensions. For example, foo.gz. Now you're checking the following, in pseudocode:

if [ foo.gz.gz does not exist ]
    compress foo.gz to foo.gz.gz
else
    don't overwrite foo.gz.gz

So, your test command will always branch off to compressing something because the test will always evaluate to true. In the end you'll always overwrite your files, because "$f.gz" will expand to foo.gz.gz.


If your real requirement is to match everything but .gz files in your current directory, Bash has easier ways to do that, e.g. by using the extglob option and negation.

#!/bin/bash
FOLDER=$1

shopt -s extglob

cd "$FOLDER"
for f in !(*.gz); do
  if [[ ! -d "$f" ]]; then
    gzip "$f"
  fi
done

You can include a check for whether the file name returned isn't actually a directory—unless you want to compress directories as well.


But actually, Linux gives you better tools to find files matching certain criteria. To (recursively) find all files that don't end with .gz and compress them:

find /some/where -type f ! -iname '*.gz' -exec gzip '{}' \;

If you don't want recursion:

find /some/where -type f -maxdepth 1 ! -iname '*.gz' -exec gzip '{}' \;
share|improve this answer
    
Actually, gzip just exits with gzip: test.gz already has .gz suffix -- unchanged and status 0 when run on files that already has the extension. But it is unnecessary matching nevertheless, as you say, and the [ ! -f ] test in the question would also do unexpected things if there was a subdirectory with a dot in it that matched the glob. (You have left an echo statement in the first find example.) –  Daniel Andersson Feb 20 '13 at 13:15
    
Thanks, fixed that. –  slhck Feb 20 '13 at 13:23
    
@slhck, thanks for your help! –  Valter Silva Feb 20 '13 at 14:45
add comment

Your Answer

 
discard

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.