ls Command in Linux: List Files and Directories

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:
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:
lsThe files are sorted by name and shown in as many columns as can fit across your terminal:
cache db empty games lib local lock log mail opt run spool tmpTo list files in a specific directory, pass the directory path as an argument. For example, the following command lists the contents of /etc:
ls /etcYou can also pass multiple directories and files separated by spaces:
ls /etc /var /etc/passwdIf 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:
ls /rootls: cannot open directory '/root': Permission deniedThe 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:
ls -l /etc/hosts-rw-r--r-- 1 root root 337 Oct 4 11:31 /etc/hostsThe 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:
ls -lh /usr/bin/bash-rwxr-xr-x 1 root root 1.3M Mar 31 2024 /usr/bin/bashThe 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:
ls -alShort 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:
ls -la ~/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 .sshThe output includes . for the current directory and .. for its parent. To show hidden files without these two entries, use -A:
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:
ls -ld /var/wwwdrwxr-xr-x 4 root root 4096 Jan 12 10:42 /var/wwwAppend 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:
ls -F /etc/rc0.dK01apache2@ K02cron@ READMEThis 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:
ls -li /etc/hosts1835021 -rw-r--r-- 1 root root 337 Oct 4 11:31 /etc/hostsTwo 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:
ls -sh /var/log/syslog260K /var/log/syslogThe 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:
ls -n /mnt/backup-rw-r--r-- 1 1004 1004 2140 Feb 9 08:12 notes.txtSort ls Output
By default, ls sorts entries alphabetically by name according to the current locale. You can request name sorting explicitly with --sort=name:
ls --sort=nameUse -r to reverse the current order:
ls -rIf you need a predictable byte-by-byte order instead of locale-aware sorting, set LC_ALL to C for the command:
LC_ALL=C lsThe --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:
ls -l --group-directories-firstFor example, the following command sorts /var by modification time and reverses the result, placing the oldest entries first:
ls -ltr /varThe 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:
ls -lt /etc/*.conf | headChoose 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:
ls -lu /etc/passwd-rw-r--r-- 1 root root 2836 Sep 2 06:41 /etc/passwdUse -c for the status change time:
ls -lc /etc/passwdThese 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:
ls -l --time=birth /etc/passwdCombine 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:
ls -l --time-style=long-iso /etc/hosts-rw-r--r-- 1 root root 337 2025-10-04 11:31 /etc/hostsFor the highest precision the system can report, use --full-time, which is shorthand for -l --time-style=full-iso:
ls --full-time /etc/hosts-rw-r--r-- 1 root root 337 2025-10-04 11:31:22.477817180 +0200 /etc/hostsNanosecond 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:
ls -RCombine recursion with long format and hidden files:
ls -lRa ~/ProjectsRecursive 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:
ls -1 /etcDo 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:
find . -maxdepth 1 -type f -print0 | xargs -0 -r fileFilter 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:
ls -l *.logThe ? character matches exactly one character, which is useful for numbered or dated files:
ls -l backup?.tar.gzSquare brackets match any single character from a set, so the following command lists configuration files that start with a or b:
ls -l [ab]*.confTo list only the directories in the current path, combine -d with a pattern that ends in a slash:
ls -d */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:
ls: cannot access '*.log': No such file or directoryThat 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:
ls -lahSort all entries by modification time, with the newest entries first:
ls -latReverse time sorting to show the oldest entries first:
ls -latrSort entries by size, with the largest files first and readable size units:
ls -lhSList a directory tree recursively in long format:
ls -lR /var/logTroubleshooting
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 .
| Option | Description |
|---|---|
-l | Long format showing permissions, owner, size, and date |
-a | Show all files including hidden (. files) |
-A | Show hidden files except . and .. |
-h | Human-readable sizes (use with -l) |
-S | Sort by file size, largest first |
-t | Sort by modification time, newest first |
-r | Reverse sort order |
-R | List subdirectories recursively |
-d | Show directory info instead of contents |
-F | Append type indicator (/, *, @) to entries |
-1 | One entry per line |
-X | Sort alphabetically by file extension |
-v | Sort version numbers naturally |
-i | Show the inode number of each entry |
-s | Show allocated size in blocks (use with -h) |
-n | Long format with numeric UID and GID |
-o | Long format without the group column |
-g | Long format without the owner column |
-Z | Show the SELinux security context |
-u | Use the access time instead of the modification time |
-c | Use the status change time instead of the modification time |
--time=birth | Use the creation time when the file system provides it |
--time-style=long-iso | Print timestamps as YYYY-MM-DD HH:MM |
--group-directories-first | List 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.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

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