ls Command in Linux: List Files and Directories

By 

Updated on

13 min read

Linux ls Command

When working in a Linux terminal, you will often need to check what a directory contains or inspect a file’s permissions and ownership. The ls command handles these everyday tasks and can also show hidden files, sort entries, and walk through subdirectories.

This guide explains how to use the ls command with practical examples, including the options you will use most often in daily work.

How to Use the ls Command

The syntax for the ls command is as follows:

txt
ls [OPTIONS] [FILES]

When used without options or arguments, ls displays a list of the names of all non-hidden files in the current working directory , formatted into columns:

Terminal
ls

The files are sorted by name and shown in as many columns as can fit across your terminal:

output
cache  db  empty  games  lib  local  lock  log  mail  opt  run  spool  tmp

To list files in a specific directory, pass the directory path as an argument. For example, the following command lists the contents of /etc:

Terminal
ls /etc

You can also pass multiple directories and files separated by spaces:

Terminal
ls /etc /var /etc/passwd

If the user you are logged in with does not have read permissions to the directory, you will get a message saying that ls cannot open the directory:

Terminal
ls /root
output
ls: cannot open directory '/root': Permission denied

The sections below explain the options you will use most often.

Understanding ls -al and Long Format

The default output shows only file and directory names. Use -l (lowercase L) when you also need permissions, ownership, size, and modification time:

Terminal
ls -l /etc/hosts
output
-rw-r--r-- 1 root root 337 Oct  4 11:31 /etc/hosts

The output contains the file type and permissions, hard link count, owner, group, size, modification time, and file name.

The first character identifies the file type. In this example, - indicates a regular file. Common values are:

  • - - Regular file.
  • b - Block special file.
  • c - Character special file.
  • d - Directory.
  • l - Symbolic link.
  • p - FIFO or named pipe.
  • s - Socket.

The next nine characters show permissions for the owner, group, and others. Each set normally uses the following characters:

  • r - Permission to read the file.
  • w - Permission to write to the file.
  • x - Permission to execute the file.
  • - - The permission is not granted.

An s or S in an execute position indicates a set-user-ID or set-group-ID bit. A t or T in the final position indicates the sticky bit. See the chmod command guide for a full explanation of these special permissions.

In the example, rw-r--r-- means that the owner can read and write the file, while the group and others can only read it. The number 1 is the hard link count. The two root fields are the owner and group, followed by the file size in bytes.

Add -h to display larger sizes with units such as K, M, and G:

Terminal
ls -lh /usr/bin/bash
output
-rwxr-xr-x 1 root root 1.3M Mar 31  2024 /usr/bin/bash

The exact size and date depend on your system. You can change file ownership with the chown command.

The frequently searched ls -al command combines -a and -l, showing hidden entries in long format:

Terminal
ls -al

Short options can appear in either order, so ls -al and ls -la produce the same listing.

Show Hidden Files with -a and -A

By default, the ls command will not show hidden files. In Linux, a hidden file is any file that begins with a dot (.).

To display all files, including hidden files, use -a. Here we combine it with -l so the hidden entries also show their permissions and ownership:

Terminal
ls -la ~/
output
drwxr-x--- 10 linuxize  linuxize  4096 Feb 12 16:28 .
drwxr-xr-x 18 linuxize  linuxize  4096 Dec 26 09:21 ..
-rw-------  1 linuxize  linuxize  1630 Nov 18  2017 .bash_history
drwxr-xr-x  2 linuxize  linuxize  4096 Jul 20  2018  bin
drwxr-xr-x  2 linuxize  linuxize  4096 Jul 20  2018  Desktop
drwxr-xr-x  4 linuxize  linuxize  4096 Dec 12  2017 .npm
drwx------  2 linuxize  linuxize  4096 Mar  4  2018 .ssh

The output includes . for the current directory and .. for its parent. To show hidden files without these two entries, use -A:

Terminal
ls -lA ~/

List Directory Information (-d)

By default, ls lists the contents of a directory. To show information about the directory itself rather than its contents, use the -d option.

This is most useful when combined with -l to inspect a directory’s permissions without seeing everything inside it:

Terminal
ls -ld /var/www
output
drwxr-xr-x 4 root root 4096 Jan 12 10:42 /var/www

Append Type Indicators (-F)

The -F option appends a character to each entry that indicates its type:

  • / - Directory.
  • * - Executable file.
  • @ - Symbolic link.
  • | - FIFO.
  • = - Socket.

To show all entries with type indicators:

Terminal
ls -F /etc/rc0.d
output
K01apache2@  K02cron@  README

This makes it easy to distinguish file types at a glance without using the full long format.

Show Inodes, Block Size, and Numeric IDs

The long format always prints the same seven columns, but several options add a column or drop one.

Use -i to print the inode number, the number the file system uses to identify the file, to the left of each name:

Terminal
ls -li /etc/hosts
output
1835021 -rw-r--r-- 1 root root 337 Oct  4 11:31 /etc/hosts

Two names on the same file system that share an inode number are hard links to the same file, so -i is the quickest way to confirm that.

The -s option prints how much space the file actually takes on disk. File systems allocate space in blocks, so this number is usually a little larger than the byte size shown by -l, and it can be smaller for sparse files. Add -h to read it in familiar units:

Terminal
ls -sh /var/log/syslog
output
260K /var/log/syslog

The remaining options change who is named in the ownership columns:

  • -n - Long format with numeric user and group IDs instead of names.
  • -o - Long format without the group column.
  • -g - Long format without the owner column.
  • -Z - Print the SELinux security context, or ? when the file has none.

Reach for -n when you are listing files from another system, such as a mounted disk or a restored backup. Files store numeric ownership IDs, and ls -l resolves them through the system’s account database. The same ID might belong to a different local account, so -n avoids that ambiguity and shows the values exactly as stored:

Terminal
ls -n /mnt/backup
output
-rw-r--r-- 1 1004 1004 2140 Feb  9 08:12 notes.txt

Sort ls Output

By default, ls sorts entries alphabetically by name according to the current locale. You can request name sorting explicitly with --sort=name:

Terminal
ls --sort=name

Use -r to reverse the current order:

Terminal
ls -r

If you need a predictable byte-by-byte order instead of locale-aware sorting, set LC_ALL to C for the command:

Terminal
LC_ALL=C ls

The --sort option also supports extension, size, time, and version sorting:

  • --sort=extension (or -X) - Sort alphabetically by extension.
  • --sort=size (or -S) - Sort by file size, largest first.
  • --sort=time (or -t) - Sort by modification time, newest first.
  • --sort=version (or -v) - Sort version numbers naturally.

To keep directories together at the top of the listing, add --group-directories-first. It acts as a primary sort key, so the directories and the files are each sorted by whatever rule the other options set:

Terminal
ls -l --group-directories-first

For example, the following command sorts /var by modification time and reverses the result, placing the oldest entries first:

Terminal
ls -ltr /var

The size shown for a directory entry is not the total size of its contents. To get the size of a directory , use du.

A practical example would be to find recently modified config files:

Terminal
ls -lt /etc/*.conf | head

Choose Which Timestamp to Show

The three standard file timestamps are the modification time (mtime), access time (atime), and status change time (ctime). The mtime changes when the contents change, while the ctime changes after writes and metadata updates such as permission or ownership edits. The atime records file access, but mount options such as noatime and relatime affect when it is updated. Some file systems also record a creation time, often called the birth time.

In long format, ls displays the modification time by default. When you add -t, it also uses the modification time as the sort key. Use -u with long format to display the access time instead:

Terminal
ls -lu /etc/passwd
output
-rw-r--r-- 1 root root 2836 Sep  2 06:41 /etc/passwd

Use -c for the status change time:

Terminal
ls -lc /etc/passwd

These two options do more than swap a column. When you combine them with -t, they also change the sort key, so ls -ltu sorts by access time while ls -lu still sorts by name and only displays the access time. Without long format, GNU ls -u and ls -c sort by the selected timestamp even without -t. The long-form spellings, --time=atime and --time=ctime, do the same thing.

On systems with GNU Coreutils, --time=birth displays the creation time when the file system provides it. If no birth time is available, ls falls back to the modification time:

Terminal
ls -l --time=birth /etc/passwd

Combine it with -t as ls -lt --time=birth when you want to sort by creation time.

Add --time-style when the abbreviated date column is not precise enough. The long-iso style prints a sortable date and time with minute precision:

Terminal
ls -l --time-style=long-iso /etc/hosts
output
-rw-r--r-- 1 root root 337 2025-10-04 11:31 /etc/hosts

For the highest precision the system can report, use --full-time, which is shorthand for -l --time-style=full-iso:

Terminal
ls --full-time /etc/hosts
output
-rw-r--r-- 1 root root 337 2025-10-04 11:31:22.477817180 +0200 /etc/hosts

Nanosecond timestamps are worth knowing about when you are debugging a build system, since tools like make compare full timestamps rather than the truncated value shown by default.

List Subdirectories Recursively (-R)

The -R option tells the ls command to display the contents of the subdirectories recursively:

Terminal
ls -R

Combine recursion with long format and hidden files:

Terminal
ls -lRa ~/Projects

Recursive output is a flat series of per-directory listings rather than a tree. When you want an indented view of the hierarchy, use the tree command instead.

Show One Entry Per Line

The -1 option forces one entry per line, which makes interactive output easier to scan:

Terminal
ls -1 /etc

Do not parse ls output in scripts because file names can contain spaces, newlines, and other special characters. To process arbitrary file names safely, use null-delimited output from find with xargs -0 . For example, this command runs file on each regular file in the current directory:

Terminal
find . -maxdepth 1 -type f -print0 | xargs -0 -r file

Filter Entries with Shell Globs

To include only names that match a pattern, let the shell expand the pattern and hand ls the resulting list of names. GNU ls also provides --ignore=PATTERN and --hide=PATTERN when you want to exclude matching names from a directory listing.

To list every file with a given extension, pass a wildcard pattern:

Terminal
ls -l *.log

The ? character matches exactly one character, which is useful for numbered or dated files:

Terminal
ls -l backup?.tar.gz

Square brackets match any single character from a set, so the following command lists configuration files that start with a or b:

Terminal
ls -l [ab]*.conf

To list only the directories in the current path, combine -d with a pattern that ends in a slash:

Terminal
ls -d */
output
assets/  content/  layouts/  static/

Because the shell does the expansion, ls normally receives file names rather than the pattern itself. With Bash’s default glob settings, an unmatched pattern is passed through unchanged, and ls reports it as a missing file:

output
ls: cannot access '*.log': No such file or directory

That message means no file matched, not that something is wrong with the command. Bash’s nullglob and failglob options change how unmatched patterns behave.

Common ls Command Examples

Short options can be combined after a single dash. The following examples cover the combinations you are most likely to need.

Show hidden files in long format with human-readable sizes:

Terminal
ls -lah

Sort all entries by modification time, with the newest entries first:

Terminal
ls -lat

Reverse time sorting to show the oldest entries first:

Terminal
ls -latr

Sort entries by size, with the largest files first and readable size units:

Terminal
ls -lhS

List a directory tree recursively in long format:

Terminal
ls -lR /var/log

Troubleshooting

ls: cannot open directory: Permission denied
Your user cannot read the directory. Check the directory’s own permissions with ls -ld /path, and run the command with sudo if the contents genuinely require root access.

Argument list too long
A glob expanded to more names than the kernel allows on a single command line. Use find instead, as in find . -maxdepth 1 -name '*.log', which reads the directory entries itself rather than receiving them all as arguments.

Output has no colors
Color is not a default. Most distributions enable it through a shell alias such as ls='ls --color=auto', which does not exist in a non-interactive shell or on a freshly installed server. Pass --color=auto explicitly, or add the alias to your Bash configuration . Avoid --color=always in pipelines, since it embeds escape sequences that confuse the receiving command.

The total line does not match the file sizes
The total value counts allocated disk blocks, not bytes, and it covers only the directory currently being listed. It will not match the sum of the size column, and it is not a recursive total. Use du when you need the real size of a directory tree.

Quick Reference

For a printable quick reference, see the ls cheatsheet .

OptionDescription
-lLong format showing permissions, owner, size, and date
-aShow all files including hidden (. files)
-AShow hidden files except . and ..
-hHuman-readable sizes (use with -l)
-SSort by file size, largest first
-tSort by modification time, newest first
-rReverse sort order
-RList subdirectories recursively
-dShow directory info instead of contents
-FAppend type indicator (/, *, @) to entries
-1One entry per line
-XSort alphabetically by file extension
-vSort version numbers naturally
-iShow the inode number of each entry
-sShow allocated size in blocks (use with -h)
-nLong format with numeric UID and GID
-oLong format without the group column
-gLong format without the owner column
-ZShow the SELinux security context
-uUse the access time instead of the modification time
-cUse the status change time instead of the modification time
--time=birthUse the creation time when the file system provides it
--time-style=long-isoPrint timestamps as YYYY-MM-DD HH:MM
--group-directories-firstList directories before files

FAQ

What does ls -al mean in Linux?
ls -al combines -a and -l. It displays hidden files, including . and .., in long format with permissions, ownership, size, and modification time.

What is the difference between ls -a and ls -A?
ls -a shows all entries, including . and ... ls -A shows hidden files but omits those two special directory entries.

How do I list files sorted by date, newest first?
Use ls -lt. Add -r to reverse the order and show oldest first: ls -ltr.

How do I sort ls output alphabetically by name?
Plain ls sorts by name according to your locale. Use ls --sort=name to request name sorting explicitly, or LC_ALL=C ls when you need predictable byte-by-byte ordering.

Conclusion

The ls command is one of the most frequently used commands in Linux, and knowing its options well saves time every day. Pair it with find for searching and filtering, with stat when you need every detail about a single file, or with chmod when reviewing and adjusting file permissions.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page