Skip to content
VLSI Mentor

Linux & Bash · Part I · Module 2 · The Filesystem and Paths

Reading ls -l: What the Long Listing Tells You

A plain ls answers one question: what names are in here. That is often not the question you have. Is this a file or a directory? Has it actually been written to, or is it empty? When did it last change? Who owns it, and may I touch it? One option answers all of those at once, and its output is the single most-read line of text in day-to-day Linux work. It is also dense, unlabelled, and routinely misread in three specific ways. This chapter takes one line apart field by field, says which fields mean exactly what they appear to, and is honest about which do not.

Foundation16 min readLinuxPart IFundamentalsFilesReading Output

Part I · Module 2 · Chapter 2.5 · Reading ls -l

1. Why the Plain Listing Is Not Enough

Chapter 2.4 used ls to see what is in a directory:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ ls
docs  rtl  scripts  sim

Four names. And that is genuinely all you learn — not whether they are files or directories, not whether any of them is empty, not when they last changed, not whether you are allowed to open them.

Add one option and every one of those questions is answered at once:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l
total 16
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 docs
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 rtl
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 scripts
drwxr-xr-x 3 engineer engineer 4096 Mar 18 16:40 sim

The -l is for long: one entry per line, with details. Chapter 1.5 taught how to read the command itself — ls is the command name and -l is a short option. This chapter is about reading what came back.

2. One Line, Seven Fields

Take a single line and separate it:

Azvya Education Pvt. Ltd.VLSI Mentor
One line of ls -l, taken apart
-rw-r--r--  1  engineer  engineer  482  Mar 14 09:12  alu.sv
│           │  │        │        │    │             └── 7. name
│           │  │        │        │    └──────────────── 6. last modified
│           │  │        │        └───────────────────── 5. size in bytes
│           │  │        └────────────────────────────── 4. group
│           │  └─────────────────────────────────────── 3. owner
│           └────────────────────────────────────────── 2. link count
└────────────────────────────────────────────────────── 1. type + permissions

Seven facts, printed side by side with no headings. The columns are separated by spaces, so they line up only because ls pads them — and they stop lining up the moment one entry has a much longer name or a much bigger size.

The rest of this chapter is those seven fields, in order.

3. Field 1a: the Type Character

The very first character of the line says what kind of thing this is. It is the fastest, most useful character in the whole listing.

CharacterKind of thing
-an ordinary file
da directory
la symbolic link — a name that points at another path
c or ba device, of the kind that lives under /dev
s or ptwo ways processes talk to each other

In practice you will see -, d and l, and the first two constantly.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 docs
-rw-r--r-- 1 engineer engineer  482 Mar 14 09:12 notes.txt

docs begins with d, so it is a directory. notes.txt begins with -, so it is an ordinary file. That is more dependable than colour, which Chapter 2.4 warned is configured rather than guaranteed, and more dependable than the name — nothing requires a directory to lack a dot in its name or a file to have one.

Symbolic links get a full treatment in Module 6. For now, recognising the l is enough; such a line also shows where the link points, with an arrow after the name.

4. Field 1b: the Permission String

The next nine characters describe who may do what.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rw-r--r--

Read them as three groups of three:

Azvya Education Pvt. Ltd.VLSI Mentor
The nine characters, grouped
rw-   r--   r--
│     │     └── everyone else
│     └──────── members of the group
└────────────── the owner

Within each group the three positions are always in the same order — read, write, execute — and a letter means allowed while a dash means not allowed.

So rw-r--r-- reads: the owner may read and write; the group may read; everyone else may read. Nobody may execute it.

A script that can be run looks different:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l scripts
total 4
-rwxr-xr-x 1 engineer engineer 128 Mar 14 09:12 run.sh

The x characters are the execute permission. Chapter 2.3 explained that ./run.sh tells the shell which file; this field is the other half — whether it is allowed to run at all. A file missing its x produces Permission denied rather than command not found, which is exactly the distinction Chapter 2.3 drew.

A small number, usually 1 for a file:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-rw-r--r-- 1 engineer engineer 482 Mar 14 09:12 alu.sv
           ↑

It counts how many names point at this same data. One file, one name, count of 1 — the ordinary case.

Directories show a larger number, and the reason is a detail you already know. Chapter 2.3 established that . and .. are real entries that genuinely exist. Each of those is a name, so each is counted. A directory therefore starts at 2 — its own name in its parent, plus the . inside it — and grows as subdirectories are added, because each subdirectory contains a .. that points back.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 rtl
drwxr-xr-x 3 engineer engineer 4096 Mar 18 16:40 sim

rtl holds two files and no subdirectories, so its count is 2. sim holds one subdirectory, logs, so its count is 3.

Notice what this does not count: rtl contains two files and the number is still 2. The count is about names pointing at this directory, not about what is inside it.

Module 6 is where names and data are separated properly. The reason to know the field now is to stop reading it as "how many things are inside" — it is not, and the number will mislead you if you do.

One honesty note: the arithmetic above is how the common Linux filesystems count. A few filesystems, including the one macOS uses, count directory links differently, so a directory there can show a larger number. The meaning of the field — names pointing at this thing — is the same everywhere.

6. Fields 3 and 4: Owner and Group

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-rw-r--r-- 1 engineer engineer 482 Mar 14 09:12 alu.sv
               ↑       ↑
             owner   group

Every file has an owner — normally the user who created it — and a group. Together with the permission string they decide what any given person may do.

Chapter 1.4's id command printed your user name and your groups. The connection is direct: if the owner column matches your name, the first group of three permission characters applies to you. If instead you are a member of the listed group, the second applies. Otherwise the third.

That is enough to read a line. Module 5 is where it becomes something you can act on.

7. Field 5: Size

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-rw-r--r-- 1 engineer engineer 482 Mar 14 09:12 alu.sv
                             ↑

For an ordinary file this is the size in bytes, and it means exactly what you expect. It is the quickest way to answer "did anything actually get written?" — a size of 0 means an empty file.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l sim/logs
total 0
-rw-r--r-- 1 engineer engineer 0 Mar 18 16:40 run.log

That log exists and is empty. A program created it and wrote nothing. Knowing the difference between absent and present but empty is worth a surprising amount of debugging time.

Bytes get hard to read quickly once numbers grow, so there is an option for that:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -lh rtl
total 8
-rw-r--r-- 1 engineer engineer 482 Mar 14 09:12 alu.sv
-rw-r--r-- 1 engineer engineer 1.2K Mar 14 09:12 counter.sv

-h is for human-readable: sizes are rounded and suffixed with K, M or G. Chapter 1.5's rule applies — -l and -h are two short options, and ls -lh is the same request as ls -l -h, combined by ls itself.

8. Field 6: the Timestamp

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-rw-r--r-- 1 engineer engineer 482 Mar 14 09:12 alu.sv
                                 ↑

This is when the file's contents were last changed — not when it was created, and not when it was last read.

It is more useful than it sounds, because it answers a question you will ask constantly: is this the output of the run I just did, or something left over from yesterday?

The default format has an oddity worth knowing. Recent files show a time; older files show a year instead:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l
-rw-r--r-- 1 engineer engineer  482 Mar 14 09:12 alu.sv
-rw-r--r-- 1 engineer engineer 1024 Nov  3  2025 old_notes.txt

alu.sv changed recently enough to be shown with a time. old_notes.txt is old enough that the year is more useful than the minute. Nothing is wrong; the column simply switches format.

If you would rather have one unambiguous format, GNU ls offers one:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l --time-style=long-iso
-rw-r--r-- 1 engineer engineer  482 2026-03-14 09:12 alu.sv
-rw-r--r-- 1 engineer engineer 1024 2025-11-03 15:41 old_notes.txt

Every line now carries a full date and time, in an order that sorts correctly as text. This is a long option in Chapter 1.5's sense, and it is a GNU extension — it is not available on BSD-derived systems including macOS, where the equivalent is spelled differently. Chapter 1.6's rule applies: check the manual on the machine you are on.

Sorting by time is often what you actually want:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -lt sim/logs

-t sorts newest first. Combined with -l it answers "what changed most recently here" in one command. Two companions worth knowing: -S sorts by size, and -r reverses whatever order is in effect.

9. Field 7: the Name

Last, and the only one that needs no explanation — except for one thing it does not tell you.

A name does not determine a file's type. A directory can be called notes.txt and an ordinary file can be called rtl. Nothing prevents it. The type character in field 1 is the authority; the name is a convention people follow for their own convenience.

10. The total Line

Every long listing of a directory starts with one:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l rtl
total 8
-rw-r--r-- 1 engineer engineer  482 Mar 14 09:12 alu.sv
-rw-r--r-- 1 engineer engineer 1228 Mar 14 09:12 counter.sv

total 8 is not a count of entries, and not the sum of the size column. It is the amount of disk space the listed files occupy, measured in blocks — and the size of a block depends on the system.

It is rarely the number you want. Mentioned here only so that it stops being mysterious: two files, total 8, and neither 2 nor 1710 appears anywhere.

11. Listing a Directory Itself

A trap worth meeting deliberately. Ask for a long listing of a directory and you get its contents:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l rtl
total 8
-rw-r--r-- 1 engineer engineer  482 Mar 14 09:12 alu.sv
-rw-r--r-- 1 engineer engineer 1228 Mar 14 09:12 counter.sv

But sometimes you want the line about rtl — its own permissions, its own owner, its own timestamp. The option for that is -d:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -ld rtl
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 rtl

One line, describing the directory rather than looking inside it. Read it with §3: the leading d confirms it is a directory, and everything after is about rtl itself.

This is the fastest way to answer "who owns this directory and may I write in it" — a question that comes up constantly on shared machines.

12. Putting It Together

A listing with one of everything, read end to end:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ ls -l
total 16
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 docs
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 rtl
drwxr-xr-x 2 engineer engineer 4096 Mar 14 09:12 scripts
drwxr-xr-x 3 engineer engineer 4096 Mar 18 16:40 sim

Four directories, all leading with d. sim has a link count of 3 and the others 2, so sim is the only one with a subdirectory — which matches the module's tree, where sim holds logs. sim also has the newest timestamp. All four are owned by engineer and readable by everyone.

Now one level down:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l scripts
total 4
-rwxr-xr-x 1 engineer engineer 128 Mar 14 09:12 run.sh

An ordinary file (-), executable by everyone (x in all three groups), owned by engineer, 128 bytes, one name pointing at it. Chapter 2.3's ./run.sh would work on this file: it has the execute permission that cd-adjacent chapter said you would need.

And the empty case:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l sim/logs
total 0

No lines at all after total. The directory exists — otherwise there would be an error — and it contains nothing. Again: exists and is empty is a different fact from does not exist, and the two have different fixes.

13. Misconceptions and Limits

"The size column tells me how big a directory is." It does not, per §7. That needs du, in Module 28.

"The link count is how many files are inside." It is not, per §5. It counts names pointing at the directory itself.

"The timestamp is when the file was created." It is when the contents last changed. Linux traditionally does not record a creation time in a way ls shows.

"A .txt file is a text file." The name is a convention. Field 1 tells you file-or-directory; what is actually inside a file is answered by the file command, which Chapter 4.7 covers.

"The columns always line up, so a script can read them." This is the one with teeth. ls output is designed for people, and it breaks as input to other programs: a file name containing a space makes the columns ambiguous, and names can contain almost any character. Every experienced engineer has seen a script break on a file called run log.txt.

When you need a list of files for a program to act on, the right tool is find, which Module 14 teaches, together with the option that makes the output unambiguous. Use ls -l to look; use something else to automate.

14. Practice

Read each line and answer from the listing alone.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
drwxr-xr-x  3 engineer engineer  4096 Mar 18 16:40 sim
-rw-r--r--  1 engineer engineer     0 Mar 18 16:41 run.log
-rwxr-xr-x  1 engineer engineer  2048 Mar 14 09:12 build.sh
-rw-rw-r--  1 engineer design   8192 Mar 17 11:05 shared_notes.txt
lrwxrwxrwx  1 engineer engineer    18 Mar 18 09:00 current

Question 1. Which of the five is a directory, and which character told you?

Question 2. run.log exists. Did the program that created it write anything? Which field answers that, and what is the value?

Question 3. Which entries could be run as a program, and which field shows it?

Question 4. shared_notes.txt has a group of design rather than engineer. If you are a member of the design group but not the owner, which group of three permission characters applies to you, and what may you do?

Question 5. sim has a link count of 3 while the other directories in this module's tree have 2. What does that tell you about sim?

Question 6. You want to see the permissions and owner of sim itself rather than what is inside it. Write the command.

Question 7. Why would it be a mistake to use the size column to decide whether sim is worth deleting to free space, and which chapter covers the right tool?

15. Remember

  • ls -l prints seven facts per line: type and permissions, link count, owner, group, size, timestamp, name.
  • The first character is the type. - is a file, d is a directory, l is a symbolic link. This is more reliable than colour or than the name.
  • The nine permission characters are three groups of three — owner, group, everyone else — each in read, write, execute order. Reading them is this chapter; changing them is Module 5.
  • The link count is names pointing at the thing, not contents. A directory starts at 2 because . and .. are real entries, and grows with each subdirectory.
  • Size in bytes is exact for a file and misleading for a directory. A size of 0 means an empty file, which is a different fact from a missing one.
  • -h makes sizes readable; -t sorts by time; -d describes the directory instead of listing it.
  • The timestamp is last modified, not created, and the format switches to a year for older entries.
  • total is disk blocks, not a count and not a byte sum.
  • ls output is for people. Do not have a program read it; file names can contain spaces, and Module 14's find exists for that job.

One field in this listing has gone unexplained: why ls showed four entries when Chapter 2.3 proved that every directory also contains . and ... The next chapter answers that, and introduces the files you have not been shown yet.

Where this fits

Part of the Linux & Bash curriculum.