2

In terminal(bash) the following command produces the correct output (an integer)

ls -l | grep '.json' | grep -v 'fit-report.json' | wc -l

which correctly returns 13.

Trying the same in a shell script:

number_reports= $(ls -l | grep '.json' | grep -v 'fit-report.json' | wc -l)
echo "number of reports is $number_reports"

produces runtime errors:

line 1: ls -l | grep '.json' | grep -v 'fit-report.json' | wc -l: command not found
number of reports is 

I've tried it without the $(..) bracketing as well as storing the var as a string and executing it in another variable, but I couldn't get that working either.

1
  • What is the very first line of your script file? Also, note that you should probably just say ls *.json instead of ls -l | grep .json. Commented Apr 13, 2014 at 5:52

2 Answers 2

4

Remove spaces around =:

number_reports=$(ls -l | grep '.json' | grep -v 'fit-report.json' | wc -l)

Though parsing ls output is not recommended as your file names can have spaces and newlines.

UPDATE:

Better to use this script to get your count:

number_reports=0
while read -d ''; do
    ((number_reports++))
done < <(find . -maxdepth 1 -name "*.json" -a ! -name "fit-report.json" -print0)

echo "number_reports=$number_reports"
Sign up to request clarification or add additional context in comments.

Comments

2

If I understand correctly, you want the number of filenames F in current directory that end with .json but such that Ffit-report.json (even though you didn't exactly express this with your chain of greps and pipes).

A straightforward pure bash way, using (extended) globs and arrays:

shopt -s nullglob extglob
filenames=( !(fit-report).json )
printf "number of reports is %d\n" "${#filenames[@]}"

(no spaces around the = sign).

The use of shopt -s nullglob is so that the glob expands to nothing if there are no matches (otherwise it expands to itself verbatim) and shopt -s extglob to turn on the extended globs.

Then we build an array filenames that contains all the file names that end with .json, ignoring the file name fit-report (that's the !(fit-report) part).

Then we print the number of elements in this array (the number of elements in array filenames is ${#filenames[@]}).

If you really want the number of reports in a variable:

number_reports=${#filenames[@]}

(with no spaces around the = sign).

Note. this will not count the “hidden” filenames (e.g., .hidden.json), unless you shopt -s dotglob.

Note. Do not parse the output of ls.

1 Comment

Thanks gniourf_gniourf, I'd never heard of shopt. Both yours and anubhava's answers were equally excellent but I had to give him the checkmark cause he was first though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.