Search code examples
bashshellunary-operator

Unary operator expected when compressing static files


I'm using the following script I found here using CentOS 6.5 and GNU bash version version 4.1.2 (built-in with the OS).

#! /bin/bash

FILETYPES=( "*.html" "*.css" "*.js" "*.xml" )
DIRECTORIES="/var/www/html/phpmyadmin"
MIN_SIZE=32

for currentdir in $DIRECTORIES
do
   for i in "${FILETYPES[@]}"
   do
      find $currentdir -iname "$i" -exec bash -c 'PLAINFILE={};GZIPPEDFILE={}.gz; \
         if [ -e $GZIPPEDFILE ]; \
         then if [ `stat --printf=%Y $PLAINFILE` -gt `stat --printf=%Y $GZIPPEDFILE` ]; \
                then gzip -1 -f -c $PLAINFILE > $GZIPPEDFILE; \
                 fi; \
         elif [ `stat --printf=%s $PLAINFILE` -gt $MIN_SIZE ]; \
            then gzip -1 -c $PLAINFILE > $GZIPPEDFILE; \
         fi' \;
  done
done

But every time I execute it, I find myself with:

bash: line 5: [: 10262: unary operator expected
bash: line 5: [: 5329: unary operator expected
bash: line 5: [: 264839: unary operator expected
bash: line 5: [: 183256: unary operator expected
bash: line 5: [: 12481: unary operator expected
[...] and lots more :-(

I've tried using [[ in line 5 elif [ stat --printf=%s $PLAINFILE -gt $MIN_SIZE ]; but I get weird stuff through stdout.


Solution

  • I think your variable $MIN_SIZE doesn't make it into the subshell, hence it is empty there and not quoted and thus you get that misleading error message because the shell sees something like [ 123 -gt ] after variable expansion (not quoting is a step to the dark side and leads to hate and suffering).

    You should set that constant in the subshell:

    -exec bash -c '\
         MIN_SIZE=32; \
         PLAINFILE={};GZIPPEDFILE={}.gz; \
         if [ -e $GZIPPEDFILE ]; \
         then if [ `stat --printf=%Y $PLAINFILE` -gt `stat --printf=%Y $GZIPPEDFILE` ]; \
                then gzip -1 -f -c $PLAINFILE > $GZIPPEDFILE; \
                 fi; \
         elif [ `stat --printf=%s $PLAINFILE` -gt $MIN_SIZE ]; \
            then gzip -1 -c $PLAINFILE > $GZIPPEDFILE; \
         fi' \;
    

    And of course you should quote your stuff properly to at least get decent error messages:

    -exec bash -c '\
         MIN_SIZE=32; \
         PLAINFILE={};GZIPPEDFILE={}.gz; \
         if [ -e "$GZIPPEDFILE" ]; \
         then if [ "`stat --printf=%Y "$PLAINFILE"`" -gt "`stat --printf=%Y "$GZIPPEDFILE"`" ]; \
                then gzip -1 -f -c "$PLAINFILE" > "$GZIPPEDFILE"; \
                 fi; \
         elif [ "`stat --printf=%s "$PLAINFILE"`" -gt "$MIN_SIZE" ]; \
            then gzip -1 -c "$PLAINFILE" > "$GZIPPEDFILE"; \
         fi' \;