Molnia
Molnia

Reputation: 60

How can I count the hidden files in a directory using a shell script?

I have used this code

#!/bin/bash

ls -l
echo -n "Number of simple files : "
ls -l | egrep '^-' | wc -l 
echo -n "Number of directories : "
ls -l | egrep '^d' | wc -l
echo -n "Number of hidden files : "
ls -la | egrep '^.*\.$' | wc -l
echo -n "Number of hidden directories : "
ls -la | egrep '^d.*\.$' | wc -l
echo " End"

While I can understand how the first two egrep work I can't figure out how the last two work. More specific what does this mean '^.*\.$' ? I want a file that starts with . (hidden file) and then how I should shape my regular expression?

Upvotes: 0

Views: 2798

Answers (5)

Charles Duffy
Charles Duffy

Reputation: 295698

You shouldn't be using grep (or ls) for this task at all. See http://mywiki.wooledge.org/ParsingLs for an in-depth discussion of how ls should only ever be used for interactive display to humans.

all_files=( * )            # includes directories
directories=( */ )         # directories only
hidden_files=( .* )        # includes directories
hidden_directories=( .*/ ) # directories only

echo "Number of files: $(( ${#all_files[@]} - ${#all_directories[@]} ))"
echo "Number of directories: ${#directories[@]}"
echo "Number of hidden files: $(( ${#hidden_files[@]} - ${#hidden_directories[@]} ))"
echo "Number of hidden directories: $(( ${#hidden_directories[@]} - 2 ))"

The - 2 in the last calculation is to remove . and .., which will always be present.

Upvotes: 7

Gergo Erdosi
Gergo Erdosi

Reputation: 42073

The regex doesn't work, because '^.*\.$' matches the dot at the end of the line. Use these commands instead to count hidden files and directories:

ls -ld .* | egrep '^-' | wc -l
ls -ld .* | egrep '^d' | wc -l

Note that egrep '^d' matches . and .. too, so you need subtract 2 from the result:

ls -ld .* | egrep '^d' | wc -l | awk '{print $1 - 2}'

Alternatives:

ls -ld .* | egrep '^d' | tail -n +3 | wc -l
echo $(($(ls -ld .* | egrep '^d' | wc -l) - 2))

Upvotes: 0

askovpen
askovpen

Reputation: 2494

last two work incorrect, but

ls -la | egrep '^.*\.$' | wc -l
ls -la | egrep '^d.*\.$' | wc -l

return 2

ls -la | egrep '^.*\.$' 
ls -la | egrep '^d.*\.$' 

return

drwxr-xr-x  7 root root  4096 date time .
drwxr-xr-x 31 root root  4096 date time ..

variant:

secret files:
ls -la | grep '^-' |awk '{print $9}' |egrep '^\.[^\.]' |wc -l
secret dirs:
ls -la | grep '^d' |awk '{print $9}' |egrep '^\.[^\.]' |wc -l

Upvotes: 1

Pankrates
Pankrates

Reputation: 3095

Note that your approach of parsing ls output for this purpose is wrong. See @Dharles Duffy's answer for a better alternative. To answer your question though and explain the regex a little bit:

'^.*\.$' means

^     // From the beginning of the string
.*    // match zero or more of any character
\.    // match one literal full-stop
$     // end of the string

I am not sure what you mean with a "secret" file but if you mean a hidden file, i.e. one that begins with . and then a filename, the way to regex that would be

'^\..*$'

Note that this is not when parsing ls output and is just for a file or directory name and does not discern between the two.

Upvotes: 1

Jake H
Jake H

Reputation: 1740

find $THE_DIRECTORY -maxdepth 1 -type f -name '.*' | wc --lines

Should work, you may want to use -L if you want to find symlinks as well.

Upvotes: 0

Related Questions