Pirijan
Pirijan

Reputation: 3579

errors executing bash command in shell script variable

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.

Upvotes: 2

Views: 135

Answers (2)

gniourf_gniourf
gniourf_gniourf

Reputation: 46813

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.

Upvotes: 2

anubhava
anubhava

Reputation: 784958

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"

Upvotes: 4

Related Questions