0

I am building a bourne script for a class, and am encountering an issue with this loop. Basically I am building a loop to go through all the files in a specified directory and determine how many files and directories there are as well as how many files are readable, writeable, and/or executable. The issue is, when I run the script it returns the following errors:

assignment4.sh: line 61: expr: command not found
assignment4.sh: line 61: expr: command not found
assignment4.sh: line 36: expr: command not found
assignment4.sh: line 41: expr: command not found
assignment4.sh: line 48: expr: command not found
assignment4.sh: line 55: expr: command not found
assignment4.sh: line 36: expr: command not found
assignment4.sh: line 41: expr: command not found
assignment4.sh: line 48: expr: command not found
assignment4.sh: line 36: expr: command not found
assignment4.sh: line 41: expr: command not found
assignment4.sh: line 48: expr: command not found

the section of code causing this error is as follows:

for filename in "$PATH"/"$1"/*
do
    if [ -f "$filename" ]
    then
        files=`expr $files + 1`

        if [ -r "$filename" ]
        then 
        readable=`expr $readable + 1`
        fi

        if [ -w "$filename" ]
        then    
            writeable=`expr $writeable + 1`
        fi

        if [ -x "$filename" ]
        then 
            executable=`expr $executable + 1`
        fi
    elif [ -d "$filename" ] 
    then
        directories=`expr $directories + 1`
    fi
done

I know that expr is on the machine I'm running because I used it earlier and it was working, though I did have to change the format of my statement utilizing it as before they were formatted

var=`expr $var+1`

and were not updating the variable's value the correct way.

neomang
  • 117
  • 3
  • 10
  • Have you changed your `$PATH`? What does `type -a expr` print? – Keith Thompson Dec 04 '14 at 01:14
  • Bourne, or POSIX sh? Moderately-old Solaris is the only remotely modern operating system where `/bin/sh` is still pre-POSIX Bourne; dash, ash, busybox sh, etc. are POSIX sh compliant (a standard itself derived in large part from ksh), not Bourne. – Charles Duffy Dec 04 '14 at 01:19
  • 3
    From the code it looks like you chose PATH as a variable name, and accidentally overrode the shell search path. – that other guy Dec 04 '14 at 01:25
  • 1
    This is why local, non-exported variables should be lower-case -- so you don't override an environment variable or a builtin by mistake. – Charles Duffy Dec 04 '14 at 01:28
  • 1
    For readability: `test -r "$filename" && : $((readable += 1))` – William Pursell Dec 04 '14 at 12:54

2 Answers2

2

what's the $PATH of the script when it runs? expr is always present (traditionally in /bin, but in /usr/bin on linux)

but you can't iterate on $PATH/$1/*, because PATH is like /bin:/usr/bin:/usr/local/bin which does not match any directory. I think you want for filename in $(echo -n $PATH | tr : ' ')/$1/* or some such

Andras
  • 2,995
  • 11
  • 17
  • I did actually change the $PATH value, because it wasn't taking my to my CWD. I think instead I'll use `for filename in \`pwd\`/$1/*` simply because I'm not sure what the `tr : ' '` section of your suggested code does, my course isn't particularly in-depth. – neomang Dec 04 '14 at 01:23
  • @Neomang, use `"$PWD/$1/"*` instead. If you don't quote the `$1`, it'll get string-split, so any filename with spaces in `$1` won't behave correctly. – Charles Duffy Dec 04 '14 at 01:27
  • Your problem was that you overwrote the value of `PATH`, which is what the shell uses to find executables like `expr`. Don't use `PATH` (or any other all-caps variable names, for that matter) for your own purposes. – chepner Dec 04 '14 at 04:03
0

If this is not Bourne but POSIX sh (that is, a shell compatible with behavior standardized in the early 90s rather than one direct from the 70s), you can use:

readable=$((readable + 1))

...rather than relying on expr.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441