Reputation: 1182
I am new with shell script. I need to save the number of files with particular extension(.properties) in a variable using shell script.
I have used
ls |grep .properties$ |wc -l
but this command prints the number of properties files in the folder. How can I assign this value in a variable.
I have tried
count=${ls |grep .properties$ |wc -l}
But it is showing error like:
./replicate.sh: line 57: ${ls |grep .properties$ |wc -l}: bad substitution
Upvotes: 2
Views: 4876
Reputation: 411
You could write your assignment like this:
count=$(ls -q | grep -c '\.properties$')
or
count=$(ls -qA | grep -c '\.properties$')
if you want to include hidden files.
This works with all kind of filenames because we're using ls
with q
.
Sure it's easier to link to some webpage that tells you to "never parse ls" than to read the ls
manual and see there's a q
option (and that most implementations default to q
if the output is to a terminal device which explains why some people here state their ls
seems to handle filenames with newlines just fine by replacing the newline with a ?
character).
Upvotes: 1
Reputation: 290075
You'd better use find
instead of parsing ls
. Then, use the var=$(command)
syntax to store the value.
var=$(find . -maxdepth 1 -name "*\.properties" | wc -l)
Reference: Why you shouldn't parse the output of ls.
To solve the problem appearing if any file name contains new lines, you can use what chepner suggests in the comments:
var=$(find . -maxdepth 1 -name "*\.properties" -exec 'echo 1' | wc -l)
so that for every match it will print not the name, but any random character (in this case, 1
) and then the amount of them will be counted to produce the correct output.
Upvotes: 2
Reputation: 531868
If you are using a shell that supports arrays, you can simply capture all such file names
files=( *.properties )
and then determine the number of array elements
count=${#files[@]}
(The above assumes bash
; other shells may require slightly different syntax.)
Upvotes: 3
Reputation: 882078
You're using the wrong brackets, it should be $()
(command output substitution) rather than ${}
(variable substitution).
count=$(ls -1 | grep '\.properties$' | wc -l)
You'll also notice I've use ls -1
to force one file per line in case your ls
doesn't do this automatically for pipelines, and changed the pattern to match the .
correctly.
You can also bypass the grep
totally if you use something like:
count=$(ls -1 *.properties 2>/dev/null | wc -l)
Just watch out for "evil" filenames like those with embedded newlines for example, though my ls
seems to handle these fine by replacing the newline with a ?
character - that's not necessarily a good idea for doing things with files but it works okay for counting them.
There are better tools to use if you have such beasts and you need the actual file name, but they're rare enough that you generally don't have to worry about it.
Upvotes: 4
Reputation: 3646
You could use a loop with globbing:
count=0
for i in *.properties; do
count=$((count+1))
done
Upvotes: 4