If you want to list just directories (in the present directory) use ls -d */

What if you want to list just ordinary files, just executable files, or just soft links, or files of any other type?

Because ls -F appends * to executable files,@ to symbolic linked files, / to directories, I tried ls -d ** and ls -d *@, but they don't work.

  • 4
    Do you have any particular version of ls in mind, perhaps the one from coreutils (GNU Linux)? Also this sounds more like a job for find. – Cristian Ciupitu Jul 28 '14 at 16:23
  • GNU coreutils 8.12.197-032bb – Tim Jul 28 '14 at 16:26

You can use the file test operators documented in man test. For example, to list symbolic links:

for i in *;do if [ -L "$i" ] ;then printf -- "%s\n" "$i";fi;done

You can use find.

List all files:

find . ! -name . -prune -type f

List all symbolic link:

find . ! -name . -prune -type l

List all executable:

find . ! -name . -prune -type f -perm +111

You can read POSIX find documentation for more advance options.


A command like ls -d *@ lists files whose name ends with @. The @ character is part of the pattern that the file name must match. When ls -F displays a character after a file name, that character is not part of the file name, it's an extra indication added by ls (that's the point of the -F option).

ls doesn't have an option to select which types of files to list. If your file names don't contain special characters such as newlines or the suffixes that ls -F adds, you can use ls -F to list certain types of files and filter its output. For example, to list symbolic links in the current directory, you can use

ls -F | grep '@$'

A more robust way to list files of a selected type is with the find command. Unlike ls, find is recursive; use the -prune action to stop the recursion. Another difference is that find doesn't treat files whose name begin with . (dot files) specially, whereas ls skips them, and shell patterns like * also skip them. For example, the following command lists the symbolic links in the current directory:

find . -name . -o -type l -print -o -prune

Another way to perform filtering is to iterate over all files in a loop and make a test to select the one you want.

for x in *; do
  if [ -L "$x" ]; then echo "$x"; fi

In zsh, you can use glob qualifiers to restrict files by type. For example, the following zsh command lists symbolic links in the current directory:

print -rl *(@)
  • I don't get it - where do you get unlike ls, find is also recursive? Rather, unlike find, ls is portably specified to handle either case. – mikeserv Jul 29 '14 at 4:48
  • @Tim - I think you mean ls */? That is a quality of the shell expanding that to a globbed argument list before then calling ls and handing it same. You can see this in action like (set -x; ls */) And to get the / at the end of all dirtypes you want ls -p. – mikeserv Jul 29 '14 at 4:50
  • Thanks. In the stdout output of ls -d *, directory names have no / at the end. Then why can ls -d */ match directories? Is / in it interpreted literally or as some special character? Note: I am using bash (I don't know which shell I should use, so I use the popular one). – Tim Jul 29 '14 at 4:52
  • @Tim - then ls -dp? And yeah, / is a special character unless you set -f in your shell to disable pathname expansion. Anyway, what Gilles doesn't mention here is that most versions of ls actually offer a fairly standardized API for tagging and filtering filenames by file-type, as is represented in your $LS_COLORS environment variable. There's more on that here. – mikeserv Jul 29 '14 at 4:57
  • @mike: As a special character, what does / mean? – Tim Jul 29 '14 at 5:01

I would suggest considering perl, because it has a useful built in operator - grep. Which unlike the command version, actually enables a 'code block' test.

So you can:

perl -e 'print join "\n", grep { -d } glob "$dir/*"'

Which which will print files matching the -d test and a variety of others:



Say you want to see only c source files (suffix .c) in a list:

ls -l *.c

This will list all c code files.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.