Using grep and ls -a commands

Nicole Romain picture Nicole Romain · May 28, 2015 · Viewed 90.1k times · Source

Using an ls –a and grep, how would you list the name of all of the files in /usr starting with the letter p or the letter r or the letter s using a single grep command?

would this be right?

ls –a | grep [prs] /usr

Answer

Stephane Chazelas picture Stephane Chazelas · May 29, 2015
 ls -a /usr | grep '^[prs]'

Would select from the output of ls -a /usr (which is the list of files in /usr delimited by newline characters) the lines that start by either of the p, r or s characters.

That's probably what your teacher is expecting but it's wrong or at least not reliable.

File names can be made of many lines since the newline character is as valid a character as any in a file name on Linux or any unix. So that command doesn't return the files whose name starts with p, q or s, but the lines of the filenames that start with p, q or s. Generally, you can't post-process the output of ls reliably.

-a is to include hidden files, that is files whose name starts with .. Since you only want those that start with p, q or s, that's redundant.

Note that:

ls /usr | grep ^[pqs]

would be even more wrong. First ^ is a special character in a few shells like the Bourne shell, rc, es or zsh -o extendedglob (though OK in bash or other POSIX shells).

Then, in most shells (fish being a notable exception), [pqs] is a globbing operator. That means that ^[qps] is meant to be expanded by the shell to the list of files that match that pattern (relative to the current directory).

So in those shells like bash that don't treat ^ specially, if there is a file called ^p in the current directory, that will become

ls /usr | grep ^p

If there's no matching file, in csh, tcsh, zsh or bash -O failglob, you'll get an error message and the command will be cancelled. In zsh -o extendedglob where ^ is a globbing operator, ^[pqs] would mean any file but p, q or s.