2

I am trying to run this script:

#!/bin/sh
cd $1
for i in */*.$2
do
   if [ 'wc –c $i' -gt $3 ]
   then
       chmod o-r $i
   fi
done

When I run the script:

./script folder1 txt 500

I get this error:

./script: line 5: [: wc –c $i: integer expression expected
./script: line 5: [: wc –c $i: integer expression expected

Any ideas why wc is not returning an integer value?

I am using GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)

Marcin Kulik
  • 845
  • 1
  • 12
  • 28

1 Answers1

6

You're using the wrong quotation marks. The code you are copying has backticks (`) around the wc command, not apostrophes ('). (The backtick is the key to the left of the number 1 on a US keyboard.)

But you should avoid using those anyway, because they have some confusing side effects that show up in nested commands; they are only there for backward compatibility, since they were the only way to do command substitution in the earliest UNIX shells. In a modern shell, use $(...) instead. You should also double-quote all your parameter expansions:

# any POSIX shell
if [ "$(wc -c <"$i")" -gt "$3" ]; then
...
fi

(I replaced wc -c "$i" with wc -c <"$i" because, as Gordon notes in the comments, wc outputs the filename along with the count; feeding the file as input means it has no filename to go by and outputs just the bare number we're looking for.)

In bash or ksh I would go one step further and use ((...)) for arithmetic comparison instead of [...]; that way you can use the normal inequality operators like > instead of -gt and friends:

# bash/ksh
if (( "$(wc -c <"$i")" > "$3" )); then
 ...
fi

The standalone ((...)) notation (as opposed to arithmetic expansion $((...)) ) is not part of POSIX, so not present in other shells. A version of it is also supported by zsh, but it's pickier about its numbers and won't work unless you get rid of the quotation marks - which works as long as the file in $i exists and $3 contains a legal number:

# zsh 
if (( $(wc -c <"$i") > $3 )); then
...
fi
Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • 3
    `wc` will output the file's name along with its size, which will also cause an error. You can avoid this by passing the file over stdin (so `wc` can't see the name) with `wc -c <"$i"` (note the `<`). Alternately, if you actually want the file size in bytes, use `stat -f %z "$i"`. – Gordon Davisson Aug 19 '17 at 02:59
  • Thank you Mark, @Gordon for helpful answers. I still get errors. Using "if (( "$(wc –c "$i")" > "$3" ));" I get: wc: –c: open: No such file or directory ./script: line 5: ((: 95 617 3828 folder2/file1.txt 95 617 3828 total > 1000 : syntax error in expression (error token is "617 3828 folder2/file1.txt 95 617 3828 total > 1000 ")... Using "if (( "$(wc –c <"$i")" > "$3" ));" I get: wc: –c: open: No such file or directory ./script: line 5: ((: > 1000 : syntax error: operand expected (error token is "> 1000 ")... the script is run from /folder, file1.txt is in /folder/folder1/folder2/file1.txt – Marcin Kulik Aug 19 '17 at 04:25
  • 1
    @FervidWhirl Something has converted the "-" in "-c" into a unicode en-dash (instead of a plain ASCII hyphen). This is causing `wc` to treat `–c` as a filename (which doesn't exist) instead of as a flag option. You may be using a text editor that "helpfully" converts plain ASCII punctuation to fancy unicode, which will break shell scripts horribly. – Gordon Davisson Aug 19 '17 at 04:28
  • thanks @Gordon, I have been using gedit I will try to use nano instead – Marcin Kulik Aug 19 '17 at 04:30