JiniKJohny
JiniKJohny

Reputation: 1182

Shell script: Count number of files in a particular type extension in single folder

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

Answers (6)

don_crissti
don_crissti

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

fedorqui
fedorqui

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

chepner
chepner

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

paxdiablo
paxdiablo

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

John B
John B

Reputation: 3646

You could use a loop with globbing:

count=0
for i in *.properties; do
    count=$((count+1))
done

Upvotes: 4

ddiez
ddiez

Reputation: 1127

Use:

count=`ls|grep .properties$ | wc -l`
echo $count

Upvotes: 1

Related Questions