32

When I use the ls command with the option -l, the first string of letters gives the info about each file, and the first letter in this string gives the file's type. (d = directory, - = standard file, l = link, etc.)

How can I filter the files according to that first letter?

1

10 Answers 10

20

You can filter out everything but directories using grep this way:

ls -l | grep '^d'

the ^ indicates that the pattern is at the beginning of the line. Replace d with -, l, etc., as applicable.

You can of course use other commands to directly search for specific types (e.g. find . -maxdepth 1 -type d) or use ls -l | sort to group similar types together based on this first character, but if you want to filter you should use grep to only select the appropriate lines from the output.

1
  • Note that if have symlinks you might want to use ls -lL. -L will follow symlinks to show if it is linked to a directory or a file.
    – Nux
    Dec 2, 2017 at 12:22
15

If you want to display all the output but have files of similar type listed together, you can sort the output on the first character of each line:

ls -l | sort -k1,1
2
  • Any reason for the downvote?
    – Joseph R.
    Nov 2, 2014 at 8:12
  • 2
    Probably due to using a text-processing routine, plain-text manipulation is perceived to be "uncool" or "wrong" amongst certain types of developers (such as most of my colleagues...). Given an upvote for a simple and correct answer. Nov 2, 2014 at 17:33
12

The command ls is dealing with file names, which are recorded in the directory data structures. So it does not really care about the file itself, including the "type" of a file.

A command that is more suited to working on actual files, not only its names, is find. It has an option that directly answers your question on how to filter the list on file type.

This gives a listing of the current directory similar to ls -l:

find . -maxdepth 1 -ls

By default, find lists directories recursively, which is disabled by limiting the search depth to 1. You can leave out the ., but I included it to show the directories need to be listed before the options.

With -type, you can filter by file type, which is expressed as f or d for plain files or directories:

find . -maxdepth 1 -type d -ls

There are other filter values for -type, notably l for symbolic links.

Note that there's a complication with symlinks: There are two types of the file in this case: l, indicating a symlink, and something like f, indicating the type of the file linked to. There are options to specify how to handle that, so you can choose.


From man find:

    -type c
           File is of type c:

           b      block (buffered) special

           c      character (unbuffered) special

           d      directory

           p      named pipe (FIFO)

           f      regular file

           l      symbolic link; this is never true if the  -L  option
                  or  the -follow option is in effect, unless the sym‐
                  bolic link is broken.  If you  want  to  search  for
                  symbolic links when -L is in effect, use -xtype.

           s      socket

           D      door (Solaris)

and relevant to the handling of symbolic links:

    -xtype c
           The  same as -type unless the file is a symbolic link.  For
           symbolic links: if the -H or -P option was specified,  true
           if the file is a link to a file of type c; if the -L option
           has been given, true if c is `l'.  In other words, for sym‐
           bolic  links, -xtype checks the type of the file that -type
           does not check.

and

    -P     Never follow symbolic links.  This is  the  default  behav‐
           iour.  When find examines or prints information a file, and
           the file is a symbolic link, the information used shall  be
           taken from the properties of the symbolic link itself.


    -L     Follow symbolic links.  When find examines or prints infor‐
           mation about files, the information  used  shall  be  taken
           from  the  properties of the file to which the link points,
           not from the link itself (unless it is  a  broken  symbolic
           link  or  find  is  unable to examine the file to which the
           link points).  Use of this option implies -noleaf.  If  you
           later  use  the -P option, -noleaf will still be in effect.
           If -L is in effect and find discovers a symbolic link to  a
           subdirectory during its search, the subdirectory pointed to
           by the symbolic link will be searched.

           When the -L option is in effect, the -type  predicate  will
           always  match  against the type of the file that a symbolic
           link points to rather than the link itself (unless the sym‐
           bolic  link  is  broken).   Using  -L causes the -lname and
           -ilname predicates always to return false.


    -H     Do not follow symbolic links, except while  processing  the
           command  line  arguments. [...]
6

from me, ls -lX can do the job

2
  • That will mix files and directories if any directory has a . in its name ...
    – AdminBee
    Nov 9, 2020 at 9:38
  • Only one that worked so far. Aug 25, 2023 at 4:58
3

If you are most concerned about ordering the folders from the other file types, you could go with

ls --group-directories-first

else, I think you have to pipe the output from ls -l through sort or through grep as answered by Anthon

1
ls -l | sort 

This will sort the result according to the alphabetical order of each result. If the first character is the criteria you want, that's it. If you need the file names only you can try:

ls -l | sort | cut -f 2 -d ' ' 

Or something similar (that command sorts and then splits each line using the space delimiter,then returns the second group.

1
  • thanks for the edit Tico, it's hard to see what you type on the phone.
    – Fabio
    Nov 3, 2014 at 14:43
1
ls -l | awk '/^d/{print $NF}

awk will catch all that start with d. as d is for directory and you need to print last field to list directory name

1
  • The "last field" will be the last whitespace-delimited word. This is not what you want if your directories contain spaces (e.g. VirtualBox VMs).
    – Kusalananda
    Aug 27, 2021 at 19:42
1

With zsh, you can use glob qualifiers to filter glob expansions by file type (among many other criteria).

So for instance, while *.txt would expand to all filenames ending in .txt regardless of the type of the corresponding file, *.txt(.) would only expand to the ones that are regular files (the ones for which the output of ls -l would start with .)

Then, you can pass the list to whatever command you like including ls -l (with -d as we want to list the files themselves, not their contents for those that are of type directory so an option you want to pass in general when passing a list of files to list as opposed to a list of directories whose contents to list):

ls -ld -- *(.)

to list regular files. See info zsh qualifiers to get the list of qualifiers. When it comes to file types, there's:

  • . for regular files as already mentioned.
  • @ for symbolic links (mnemonic: that's what ls -F appends to symlinks)
  • / for directories (same mnemonic)
  • = for sockets (same mnemonic)
  • % for devices, %b, %c for block and character devices specifically.
  • p for named pipes.

And prepending those with - causes the check to be done after symlink resolution so for instance *(-/) would list directories or symlinks to directories.

2
  • Isn't -d redundant in the command ls -ld -- *(.) since you'll only get regular files anyway?
    – Wildcard
    Aug 27, 2021 at 21:49
  • 1
    @Wildcard, I agree using it with (.) doesn't make a very strong case for it, but -d is the option you want to use when passing globs to ls so it doesn't try to list directory contents. Here, though far fetched, a regular file could have been replaced with a directory in between zsh generating the matching files and ls listing being started and processing its arguments. The ls -ld -- *... should be a coding pattern, Aug 28, 2021 at 5:42
0

This produced the file type category for each file in a directory.

ls -lx | xargs file

The file command is used to determine the type of a file. .file type may be of human-readable(e.g. 'ASCII text') or MIME type(e.g. 'text/plain; charset=us-ascii'). This command tests each argument in an attempt to categorize it.

0

If you want to only use ls. I would recommend you to use the following command line:

ls -lAht --sort=size -r --group-directories-first --color=auto

What it is doing is to sort:

  1. Directories
  2. Symlinks (their size are the length of the pathname they are pointing)
  3. All the rest of files by reverse sorted.

Another case is:

ls -lAhtL --sort=extension --group-directories-first --color=auto

it stops looking for symlink and checks for extensions instead. If symlinks are referring to a directory they will group first too.

1
  • Symlinks do not have a size 0. Do a ls -l on any directory containing symlinks and check again. The reported size for a symlink is the length of the pathname the symlink points to.
    – raj
    Oct 10, 2023 at 21:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .