0

I'm new to Unix and trying to show all the files (without directories) in my directory, so I use the command ls -p | grep -v /.

It shows me a list that looks something like this:

Process1
Process2 
Process3
   ︙

But when I use the command ls -p | grep -v / | grep P*, it shows only some of the processes. Why don't all of the processes show?

EDIT

I realized that I used capital P instead of lower case p. This is a mistake.

asaf92
  • 292
  • 3
  • 14

2 Answers2

3

The "P*" would be matching something (or not) from your shell before grep sees the parameter. If you quote it, you'll get better results, but bear in mind that grep matches regular expressions rather than globs.

So just a "P" would work. Because it is a regular expression, you do not need the asterisk * to allow the characters following "P" to be matched (grep ignores those by default):

ls -p | grep -v / | grep "P"

or

ls -p | grep -v / | grep '^P'

Following up on the altered question, to ignore case, use the -i option of grep, e.g.,

ls -p | grep -v / | grep -i '^P'

Further reading:

Thomas Dickey
  • 76,765
  • But i'm only looking for files that start with p, so using grep p will return more results than needed – asaf92 Jul 31 '16 at 10:48
  • 1
    Your question was unclear, but I addressed that in the last line of this answer. By the way, your comment uses p rather than P. If you want to ignore case, you should have made that part of the question. – Thomas Dickey Jul 31 '16 at 10:49
3

In your second command, you grep P*. This will prompt the shell to do filename globbing on P*, i.e. it will expand P* to all files starting with the letter P.

Use set -x in your shell to see what gets executed (turn tracing off with set +x). I actually have tracing turned on by default in my own interactive shell sessions just to see what I'm doing.

Just double-quoting P* won't solve this as the regular expression P* also matches filenames such as APPLE and file.PP, and actually hello_world.c and all other filenames as well as P* also matches filenames with no Ps in them.

Generally, you shouldn't parse the output of ls though, so the following would be a better way of getting a list of files (not directories) starting with the letter P:

$ find . -type f -maxdepth 1 -name "P*"

This will find all regular files (-type f) in the current directory (.) with names starting with P (-name "P*"). The -maxdepth 1 option restricts find to only this directory. It would otherwise recurse down into subdirectories as well.

To do with find what you're doing with grep -v /, i.e. removing the directories from the list rather than selecting the regular files:

$ find . ! -type d -maxdepth 1 -name "P*"

This will also find non-regular files, such as sockets etc. In some shells it's necessary to escape or quote the !, i.e. saying

$ find . "!" -type d -maxdepth 1 -name "P*"

or

$ find . \! -type d -maxdepth 1 -name "P*"

Note that the quoting of P* is important so that your shell doesn't expand it.

Kusalananda
  • 333,661