Home / Learn Linux / Lesson 5
Listing files: ls, file types and timestamps
Read ls -l line by line, spot file types, and understand when a file was read, changed and modified.
- Lesson
- 5 of 30
- Time
- About 35 minutes
On this page
- Reading ls -l
- The options you'll actually use
- Sorting by time
- File types
- Three timestamps
- Common mistakes
- Practice
- Cheat sheet
Reading ls -l
ls -l is the command you'll run more than any other, so it's worth being able to read every column. Here's one line:
$ ls -l /etc/hostname
-rw-r--r-- 1 root root 6 Oct 21 11:01 /etc/hostnameLeft to right:
| Part | Here | Means |
|---|---|---|
| Type | - | A regular file. d is a directory, l a link (more below) |
| Permissions | rw-r--r-- | Who may read, write and run it (lesson 14) |
| Links | 1 | How many names point to this file (lesson 11) |
| Owner | root | The user who owns it |
| Group | root | The group it belongs to |
| Size | 6 | In bytes |
| Date | Oct 21 11:01 | When the contents last changed. Files older than six months show the year instead of the time |
| Name | /etc/hostname | The file |
For a directory, the size is just the space its list of names takes up, usually 4096, not the size of what's inside. Lesson 25 shows how to measure that with du.
The total line at the top of a directory listing is the disk space the listed files use, counted in 1 KiB blocks. You can mostly ignore it.
Try it
- Who owns
/etc/passwd, and how big is it? - Who owns your home directory?
Answer
$ ls -l /etc/passwd -rw-r--r-- 1 root root 1778 Oct 21 11:33 /etc/passwd $ ls -ld ~ drwxr-x--- 14 ubuntu ubuntu 4096 Oct 21 11:29 /home/ubuntu
root owns /etc/passwd. Your home directory belongs to ubuntu. Plain ls -l ~ would list what's inside it; -d lists the directory itself (see the next section).
The options you'll actually use
| Option | Does |
|---|---|
-l | Long format |
-a / -A | Show hidden files (with / without . and ..) |
-h | Human sizes: 4.0K, 12M, 1.2G |
-t | Newest first |
-r | Reverse whatever order you asked for |
-S | Biggest first |
-d | List a directory itself, not what's inside it |
-R | Go into every subdirectory too |
-1 | One name per line |
-F | Add a symbol showing each entry's type |
They combine. ls -lh is the everyday version of ls -l:
$ ls -lh /var/log
total 1.9M
lrwxrwxrwx 1 root root 39 Jul 20 16:33 README -> ../../usr/share/doc/systemd/README.logs
-rw-r--r-- 1 root root 13K Oct 21 11:21 alternatives.log
-rw-r----- 1 root adm 0 Oct 21 11:01 apport.log
drwxr-xr-x 2 root root 4.0K Oct 21 11:33 apt
-rw-r----- 1 syslog adm 624K Oct 21 11:35 auth.log
...-lS sorts by size, which is handy for finding what's filling a directory:
$ ls -lhS /var/log
total 1.9M
-rw-r----- 1 syslog adm 624K Oct 21 11:35 auth.log
-rw-r----- 1 syslog adm 471K Oct 21 11:35 syslog
-rw-r----- 1 syslog adm 312K Oct 21 11:06 cloud-init.log
-rw-rw-r-- 1 root utmp 290K Oct 21 11:33 lastlog
...-d matters when you want details about a directory instead of its contents:
$ ls -ld /etc /var/log
drwxr-xr-x 107 root root 4096 Oct 21 11:33 /etc
drwxrwxr-x 10 root syslog 4096 Oct 21 11:35 /var/logYou can list as many paths as you like in one go, and use wildcards: * matches anything, so /etc/*.conf means every name in /etc ending in .conf:
$ ls -l /etc/*.conf
-rw-r--r-- 1 root root 4027 Nov 4 2025 /etc/adduser.conf
-rw-r--r-- 1 root root 6430 Oct 21 11:03 /etc/ca-certificates.conf
-rw-r--r-- 1 root root 2967 Feb 16 2026 /etc/debconf.conf
-rw-r--r-- 1 root root 1706 Nov 4 2025 /etc/deluser.conf
-rw-r--r-- 1 root root 1289 Jan 6 2026 /etc/dhcpcd.conf
...The shell expands the * into the matching names before ls even runs. Lesson 9 covers wildcards properly.
Try it
- Show
/usr/binwith human sizes, biggest first, and only the first few lines. - List every file in
/etcwhose name starts withhost.
Answer
$ ls -lhS /usr/bin total 171M -rwxr-xr-x 1 root root 18M Sep 4 07:31 perf -rwxr-xr-x 116 root root 11M Sep 3 08:01 coreutils -rwxr-xr-x 1 root root 8.4M Mar 15 2026 bpftrace -rwxr-xr-x 1 root root 7.2M Aug 20 10:41 python3.14 ... $ ls -l /etc/host* -rw-r--r-- 1 root root 92 Apr 20 2026 /etc/host.conf -rw-r--r-- 1 root root 6 Oct 21 11:01 /etc/hostname -rw-r--r-- 1 root root 237 Oct 21 11:09 /etc/hosts -rw-r--r-- 1 root root 411 Jul 20 16:36 /etc/hosts.allow -rw-r--r-- 1 root root 711 Jul 20 16:36 /etc/hosts.deny
For the first one, ls -lhS /usr/bin | head -5 cuts it to five lines (lessons 6 and 8 explain head and |).
Sorting by time
-t puts the newest first. Add -r and the newest goes to the bottom, right above your prompt, which is where you want it when a directory has hundreds of files:
$ ls -ltr /var/log
total 1940
...
-rw-r----- 1 syslog adm 161818 Oct 21 11:35 kern.log
-rw-r--r-- 1 root ubuntu 24576 Oct 21 11:35 wtmp.db
-rw-r----- 1 syslog adm 481738 Oct 21 11:35 syslog
-rw-r----- 1 syslog adm 638830 Oct 21 11:35 auth.logls -ltr is the classic first move when something just went wrong: the logs that changed last are the ones to read.
Try it
- Which file in
/etcchanged most recently?
Answer
$ ls -lt /etc
total 932
-rw-r--r-- 1 root root 56 Oct 21 11:33 subgid
...The first file after total is the newest.
File types
The first character of each ls -l line tells you what kind of thing it is:
| Character | Type | Example |
|---|---|---|
- | Regular file | /etc/hostname |
d | Directory | /etc |
l | Symbolic link (points to another path) | /bin |
c | Character device (a stream of bytes) | /dev/null, terminals |
b | Block device (a disk) | /dev/vda |
s | Socket (programs talk through it) | /run/systemd/notify |
p | Named pipe | Rare, lesson 8 mentions them |
You can see several at once:
$ ls -ld /etc/hostname /etc /bin /dev/null /dev/vda
lrwxrwxrwx 1 root root 7 Apr 20 2026 /bin -> usr/bin
crw-rw-rw- 1 root root 1, 3 Oct 21 11:06 /dev/null
brw-rw---- 1 root disk 253, 0 Oct 21 11:06 /dev/vda
drwxr-xr-x 107 root root 4096 Oct 21 11:33 /etc
-rw-r--r-- 1 root root 6 Oct 21 11:01 /etc/hostnamels -F shows the type as a symbol after each name instead: / for a directory, @ for a link, * for a file you can run, | for a pipe, = for a socket:
$ ls -F /
bin@ dev/ home/ lost+found/ mnt/ proc/ run/ snap/ sys/ usr/
boot/ etc/ lib@ media/ opt/ root/ sbin@ srv/ tmp/ var/What's inside: the file command
Linux doesn't care about file extensions. A file called photo.txt can be a JPEG, and a program can have no extension at all. file looks at the contents and tells you what it really is:
$ file /etc/hostname /usr/bin/ls /etc /bin /dev/vda /usr/share/doc/bash/README.gz
/etc/hostname: ASCII text
/usr/bin/ls: symbolic link to ../lib/cargo/bin/coreutils/ls
/etc: directory
/bin: symbolic link to usr/bin
/dev/vda: block special (253/0)
/usr/share/doc/bash/README.gz: gzip compressed data, max compression, from Unix, original size modulo 2^32 4848/usr/bin/ls turns out to be a link. On Ubuntu 26.04, ls, cat and dozens of other commands are all links to one program, the Rust coreutils, which checks the name it was started with and behaves as that command.
Use file whenever you're not sure whether something is text you can open, a program or an archive.
Try it
- What type of thing is
/dev/null, and what's/dev/sdaor/dev/vdaon your machine? - What kind of file is
/usr/bin/tldr?
Answer
$ ls -l /dev/null /dev/vda crw-rw-rw- 1 root root 1, 3 Oct 21 11:06 /dev/null brw-rw---- 1 root disk 253, 0 Oct 21 11:06 /dev/vda $ file /usr/bin/tldr /usr/bin/tldr: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=723ebba5126c17c813e77e3e4d0ff5e036ec8585, for GNU/Linux 3.7.0, stripped
/dev/null is a character device (c) and /dev/vda a block device (b), the VM's disk. tldr is a compiled program. On an Intel or AMD PC it says x86-64 instead of ARM aarch64.
Three timestamps
Every file has three times, and ls -l shows only one of them:
- mtime (modified): when the contents last changed. This is what
ls -lshows. - atime (accessed): when the contents were last read.
- ctime (changed): when the file's details last changed: its permissions, owner, name or contents. People often think the c means "created". It doesn't.
Many filesystems also keep a birth time, when the file was created. stat shows them all. Make a practice directory and a file to play with (mkdir makes a directory, echo with > writes a file; lessons 7 and 8 cover both):
$ mkdir ~/ls-lab $ cd ~/ls-lab $ echo hello > note.txt $ stat note.txt File: note.txt Size: 6 Blocks: 8 IO Block: 4096 regular file Device: 253,1 Inode: 534053 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu) Access: 2026-10-21 11:36:26.137964455 +0000 Modify: 2026-10-21 11:36:26.138028581 +0000 Change: 2026-10-21 11:36:26.138028581 +0000 Birth: 2026-10-21 11:36:26.137964455 +0000
Now watch them move. Reading the file doesn't change mtime. Changing its permissions changes ctime only:
$ cd ~/ls-lab $ cat note.txt hello $ stat --printf="access %x\nmodify %y\nchange %z\n" note.txt access 2026-10-21 11:36:26.264965446 +0000 modify 2026-10-21 11:36:26.138028581 +0000 change 2026-10-21 11:36:26.138028581 +0000 $ chmod 600 note.txt $ stat --printf="access %x\nmodify %y\nchange %z\n" note.txt access 2026-10-21 11:36:26.264965446 +0000 modify 2026-10-21 11:36:26.138028581 +0000 change 2026-10-21 11:36:26.266965462 +0000
stat --printf prints only the fields you ask for: %x, %y and %z are access, modify and change, and \n starts a new line. stat -c does the same but always adds one line break at the end, which is simpler when you want a single field.
The access time moved when cat read the file, and chmod moved only the change time. Ubuntu doesn't update atime on every single read, because writing to the disk every time a file is read would slow everything down. It updates it only when the old access time is earlier than the modify or change time, or more than a day old. That rule is called relatime, and it's why atime is only a rough guide.
Changing timestamps: touch
touch sets a file's access and modify times to now. If the file doesn't exist, it creates an empty one, which is how most people use it (lesson 7). It can also set any time you like, which is useful for testing scripts that clean up "files older than 30 days":
$ cd ~/ls-lab $ touch -d "2026-01-15 09:30" old.txt $ touch new.txt $ ls -l total 4 -rw-rw-r-- 1 ubuntu ubuntu 0 Oct 21 11:36 new.txt -rw------- 1 ubuntu ubuntu 6 Oct 21 11:36 note.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Jan 15 2026 old.txt
Seeing the other times with ls
ls sorts and shows mtime by default. -u switches it to atime and -c to ctime. Together with -t, they sort by that time:
$ cd ~/ls-lab $ ls -lt total 4 -rw-rw-r-- 1 ubuntu ubuntu 0 Oct 21 11:36 new.txt -rw------- 1 ubuntu ubuntu 6 Oct 21 11:36 note.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Jan 15 2026 old.txt $ ls -ltu total 4 -rw-rw-r-- 1 ubuntu ubuntu 0 Oct 21 11:36 new.txt -rw------- 1 ubuntu ubuntu 6 Oct 21 11:36 note.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Jan 15 2026 old.txt $ ls -ltc total 4 -rw-rw-r-- 1 ubuntu ubuntu 0 Oct 21 11:36 new.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Oct 21 11:36 old.txt -rw------- 1 ubuntu ubuntu 6 Oct 21 11:36 note.txt
Try it
- Make a file called
report.txtdated 1 March 2026 at noon, and check it withls -l. - Which of the three times does
chmodchange? - Print just the modify time of
/etc/hostname.
Answer
$ cd ~/ls-lab $ touch -d "2026-03-01 12:00" report.txt $ ls -l report.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Mar 1 2026 report.txt $ stat -c %y /etc/hostname 2026-10-21 11:01:58.431302254 +0000
chmod changes only ctime, because it changes the file's details, not its contents.
Common mistakes
- **Reading the date in
ls -las the creation date.** It's the last time the contents changed. Usestatand look at Birth for creation. - Thinking ctime means created. It means changed: permissions, owner, name or contents.
- Trusting extensions. Check with
file. - **
ls -lon a directory when you wanted the directory itself.** Add-d. - Expecting a directory's size to include its contents. The
4096is the directory's own list of names. Usedu -sh dir(lesson 25).
Practice
- List
/var/logwith human sizes, the newest file at the bottom.
Answer
$ ls -lhtr /var/log
total 1.9M
drwxr-xr-x 2 root root 4.0K May 29 18:58 dist-upgrade
...
-rw-r--r-- 1 root ubuntu 24K Oct 21 11:35 wtmp.db
-rw-r----- 1 syslog adm 471K Oct 21 11:35 syslog
-rw-r----- 1 syslog adm 624K Oct 21 11:35 auth.log- In
~/ls-lab, make three files:a.txtdated 1 January 2026,b.txtdated 1 June 2026 andc.txtdated now. List them oldest first.
Answer
$ cd ~/ls-lab $ touch -d 2026-01-01 a.txt $ touch -d 2026-06-01 b.txt $ touch c.txt $ ls -ltr a.txt b.txt c.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Jan 1 2026 a.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Jun 1 00:00 b.txt -rw-rw-r-- 1 ubuntu ubuntu 0 Oct 21 11:36 c.txt
- Show one line each for
/etc,/etc/hostname,/binand/dev/null, and say what type each one is from the first character.
Answer
$ ls -ld /etc /etc/hostname /bin /dev/null
lrwxrwxrwx 1 root root 7 Apr 20 2026 /bin -> usr/bin
crw-rw-rw- 1 root root 1, 3 Oct 21 11:06 /dev/null
drwxr-xr-x 107 root root 4096 Oct 21 11:33 /etc
-rw-r--r-- 1 root root 6 Oct 21 11:01 /etc/hostnamed directory, - regular file, l link, c character device.
- Find out what kind of file
/usr/share/common-licenses/GPL-3is without opening it.
Answer
$ file /usr/share/common-licenses/GPL-3
/usr/share/common-licenses/GPL-3: ASCII text- Print the size in bytes and the owner of
/etc/passwdusingstat -c. (%sis the size and%Uthe owner.)
Answer
$ stat -c "%s bytes, owned by %U" /etc/passwd
1778 bytes, owned by root- Read
note.txtin~/ls-lab, then show which of its three times changed.
Answer
$ cd ~/ls-lab $ stat --printf="access %x\nmodify %y\nchange %z\n" note.txt access 2026-10-21 11:36:26.264965446 +0000 modify 2026-10-21 11:36:26.138028581 +0000 change 2026-10-21 11:36:26.266965462 +0000 $ cat note.txt hello $ stat --printf="access %x\nmodify %y\nchange %z\n" note.txt access 2026-10-21 11:36:27.293973476 +0000 modify 2026-10-21 11:36:26.138028581 +0000 change 2026-10-21 11:36:26.266965462 +0000
Because of relatime, the access time only moves if it was earlier than the modify or change time, or more than a day old. Here it moved, because chmod had just updated the change time.
Cheat sheet
| Command | What it does |
|---|---|
ls -l | Long listing: type, permissions, links, owner, group, size, date, name |
ls -lh | Human-readable sizes |
ls -la, ls -lA | Include hidden files |
ls -lt, ls -ltr | Newest first, newest last |
ls -lS | Biggest first |
ls -ld dir | The directory itself |
ls -F | / dir, @ link, * program |
ls -lu, ls -lc | Show access time, change time |
file name | What the contents really are |
stat name | Every detail, all timestamps |
stat -c %y name | Just the modify time |
touch name | Set times to now (or create the file) |
touch -d "2026-01-15 09:30" name | Set a specific time |
← The Linux filesystem and pathsReading files: cat, less, head and tail →