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
  • Process? You mean "files"? – Kusalananda Jul 31 '16 at 10:41
  • Do you have several files named `Process...`? – JigglyNaga Jul 31 '16 at 10:42
  • It's not really "Process", it's some other names but all start in the same letter and only some show when I use `ls -p | grep -v / | grep P*` – asaf92 Jul 31 '16 at 10:44
  • What shell are you using? – JigglyNaga Jul 31 '16 at 10:45
  • I'm using tcsh. – asaf92 Jul 31 '16 at 10:46
  • 1
    In some 30 years of UNIX, this is the first time I saw somebody actually use `ls -p`. Congratulations, there must be a prize waiting for you somewhere. :) – Satō Katsura Jul 31 '16 at 11:04
  • See [List only regular files (but not directories) in current directory](http://unix.stackexchange.com/a/116524) for instance. Using `ls -p` for the purpose of filtering (in or out) directories is not uncommon (even though it's flawed in that it doesn't handle filenames with newline characters). – Stéphane Chazelas Jul 31 '16 at 11:14
  • I actually learned to use `ls -p` from the link above, but i'll still have my prize please. – asaf92 Jul 31 '16 at 11:22
  • (1) Please don’t use `Process1`, `Process2`, `Process3`, etc., as example ***file*** names.  This is almost as confusing as using `Directory1`, `Directory2`, and `Directory3` as example file names and `File1`, `File2`, and `File3` as example directory names.  More to the point, don’t say that `ls` lists processes; that’s wrong.  (2) Please don’t edit your question to say “I made a mistake.”  Edit it ***to fix the mistake.***  Add a comment if people have clearly been investing a lot of effort into the wrong version of the question, but don’t clutter up the question itself with change markings. – Scott - Слава Україні Jul 31 '16 at 16:23
  • Also, see [command `ls /etc | grep d*` is yielding no results but `ls /etc | grep p*` lists entire directory](http://unix.stackexchange.com/q/149340/23408). – Scott - Слава Україні Jul 31 '16 at 16:39

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
  • 75,040
  • 9
  • 171
  • 268
  • 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
  • 320,670
  • 36
  • 633
  • 936