1

I need for my home assignment somehow to get a list of all the files starting with the letter F, I know of the command:

ls F*

But it also gives me directories, is it possible to only show actual files?

cuonglm
  • 153,898
user142424
  • 31
  • 1
  • 2
  • 5

3 Answers3

4

POSIXly:

find . ! -name . -prune -type f -name 'F*'

With zsh:

print -rl -- F*(.)
cuonglm
  • 153,898
1

Sure - using find (which does not sort names as ls does, so I added that):

find . -type f -maxdepth 1 -name 'F*' |sort |xargs ls -l {} \;

or (if you want only the names)

find . -type f -maxdepth 1 -name 'F*' |sort

The -maxdepth option is not in POSIX, but since you tagged this with bash, we can make some assumptions. For instance, it works with OSX (the other platform where people generally use bash).

In any case, left to itself, find will show files in subdirectories, which is something that ls will not do without adding a -R option.

One issue with find is that its output may include filenames with nonprinting characters (blanks, etc). Both Linux and OSX find provide an extension (not in POSIX) called -print0, which works with xargs complementary extension -0. So you could do this:

find . -type f -maxdepth 1 -print0 -name 'F*'  |sort -z |xargs -0 ls -l {} \;

or (if you want to give up the sorting feature), you could use straight POSIX:

find . -type f -maxdepth 1 -name 'F*' -exec ls -l {} +

Sorting is mainly an issue when you want a detailed listing, but the POSIX + would not be helpful if you want a sorted list, since (still legal) newlines in the list of names would interfere with sorting.

@cuonglm points out that POSIX has the -prune option, which says:

-prune
The primary shall always evaluate as true; it shall cause find not to descend the current pathname if it is a directory.

and if you are using "." for the argument of find (as done here), then there is no need of the -maxdepth option. True enough, but if we pursue the analogy to ls further, then "." is the equivalent of ls -a, while strictly matching OP's question would drop the "-a" option and the argument to find could be "*". However (as reminded by @cuonglm), -prune is only useful for directories, and find * -prune would match directory contents.

One could also use a shell wildcard expansion, e.g.,

for n in F*;do [ -f "$n" ] && echo "$n"; done

which is (probably) preferable to ls F* since it does not convert nonprinting characters into question marks, wildcard expansion in either case runs into command-length restrictions.

Ultimately, the answer depends on whether OP wants a listing or a list of names. But in either case, ls by itself cannot do the job.

Thomas Dickey
  • 76,765
  • -maxdepth is not POSIX – Stéphane Chazelas Nov 29 '15 at 20:55
  • -type f only selects regular files and not the other types of non-directories (the OP's question is unclear though since directories are just one of many types of files). Use ! -type d for non-directories. [ -f "$n" ] returns true for regular files and symlinks to regular files. [ ! -d "$n" ] || [ -L "$n" ] for non-directories. – Stéphane Chazelas Nov 29 '15 at 20:58
1

I could use the find command:

find ./ -name "F*" -type f

-type f means you want regular files only.