Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a question concerning linux commands. How do I count all the files that begin with letters from a to g?

share|improve this question
    
The file names, or the file contents? In a single directory, in a whole directory tree? –  Gilles Nov 8 '12 at 23:15

5 Answers 5

You can do it with a one-line shell command:

find / -name '[abcedfg]*' -print | wc -l

You will see some messages about how find doesn't have permission to read some directory or another, but you will get a count of files whose names begin with those 7 letters.

share|improve this answer
    
any reason to specify [abcedfg] vs just [a-g]? –  amphibient Nov 8 '12 at 20:37
    
Just a habit for me. Those two shell globs should match the same file names, but I think seeing all the characters in a range is clearer, at least for small numbers of characters. –  Bruce Ediger Nov 8 '12 at 21:24
1  
Note that files with newline characters in their path will be counted several times. –  Stéphane Chazelas Nov 8 '12 at 21:39
4  
@foampile, the behavior of meaning ranges is locale dependant. [a-g] will match é in most non-ASCII locales contrary to [abcdefg] –  Stéphane Chazelas Nov 8 '12 at 21:45

GNU find can do that for you:

find ./ -type f -maxdepth 1 -iname "[a-g]*" 2> /dev/null | wc -l

this finds all files (not directories) under ./ but digs into no further directories and matches the name (case insensitive) of the file beginning with "a-g", redirects all errors to /dev/null and then counts the files

share|improve this answer

The GNU implementation of the ls command (which you are using since you are running Linux) will find all files in the current directory starting with a character a-g.

ls --ignore='[!a-g]*'

It tells to ignore all files that do not start with a character in the range [a-g]. The ! inverts the filter. * indicat

Next run the output through wc -l to count the lines.

The full command will thus be:

ls --ignore='[!a-g]*' | wc -l

This solution will not recurs into subdirectories.

share|improve this answer
    
I'm running Linux and my ls is implemented by BusyBox. Maybe you should explain why you're inverting the pattern then ignoring it, rather than just doing ls [a-g]* (I assume in order to handle the case of 0 matches, or the glob expanding into too many arguments.) And as @StephaneChazelas says in a comment to another answer, why not add -d to avoid recursing into directories? –  dubiousjim Nov 9 '12 at 17:34
    
@dubiousjim -d wouldn't help here as ls is not given any argument so it defaults to the current directory. With -d, it would just return "." –  Stéphane Chazelas Nov 9 '12 at 18:35
    
Right you are, thanks for the correction. –  dubiousjim Nov 9 '12 at 18:57
LC_ALL=C
set -- [a-gA-G]*
if [ "$1" = '[a-gA-G]*' ]; then
  echo 0
else
  echo "$#"
fi          
share|improve this answer
4  
+1 for using shell internal commands only ;o) –  jippie Nov 8 '12 at 21:41
    
You of all people might have mentioned zsh: print -lr [A-Ga-g]*(N) (or print -lr (#i)[a-g]*(N) if you want to be fancy). –  Gilles Nov 8 '12 at 23:18
    
@Gilles, You mean n=0;: (#i)[a-g]*(Ne:'((!++n))':) ? ;-) –  Stéphane Chazelas Nov 9 '12 at 6:26
    
@StephaneChazelas Ah, oops, I somehow dropped “count” when I wrote this. (a=((#i)[a-g]*(N)); echo $#a) is less typing (and less cryptic). –  Gilles Nov 9 '12 at 11:06
    
@Gilles, I was going to say it's less efficient as it sorts the list (which you can disable with newers versions of zsh though) and stores it in memory, but in fact, it appears to be faster because for some reason mine causes zsh to do a lstat(2) on each file –  Stéphane Chazelas Nov 9 '12 at 11:53
ls -1 [a-g]* | wc -l

Why do it like this? Because you probably want the simplest answer; this one assumes you don't have to worry about not counting directories, nor searching sub-directories, nor upper-case filenames... and this is the command I most often use.

share|improve this answer
    
-1 is not necessary when the output is not to a terminal (like a pipe or socketpair (ksh93) above). What's the harm in adding a -d option and make it correct? –  Stéphane Chazelas Nov 9 '12 at 12:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.