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?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityI could use the find command:
find ./ -name "F*" -type f
-type f means you want regular files only.
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.
-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.
Nov 29, 2015 at 20:58