Read Directory Contents Reliably with vdir

vdir is GNU's verbose directory listing, the command ls -l quietly aliases to when you want the long format by default. You will finish with a small set of commands for checking a directory, including hidden entries, long metadata, the directory itself and recursive output, and know which of those are safe for a human check versus a script.

This guide uses GNU coreutils 9.4, installed here as package version 9.4-3ubuntu6.3. Allow about ten minutes. You need a shell and read access to the directory you want to inspect. The examples only read directory metadata and do not need sudo.

1. Confirm the installed command

vdir is the verbose directory-listing command from GNU coreutils, defaulting to the current directory. Start by checking the binary and version:

$ command -v vdir
/usr/bin/vdir
$ vdir --version | head -1
vdir (GNU coreutils) 9.4
$ dpkg-query -W -f='${Package} ${Version}\n' coreutils
coreutils 9.4-3ubuntu6.3

Checkpoint: if command -v finds a different implementation, or the version is not 9.4, run vdir --help and check the local option meanings before copying these examples unchanged.

2. List the current directory

Run vdir with no arguments for a long listing of the current directory:

$ vdir
total 12
-rw-r--r-- 1 alice alice  842 Sep 27 17:20 notes.txt
drwxr-xr-x 2 alice alice 4096 Sep 27 17:18 reports
-rw-r--r-- 1 alice alice  126 Sep 27 17:19 todo.txt

The exact names, times and sizes will differ on your machine. The fields, in order, are mode, link count, owner, group, size, modification time and name. A directory's displayed size is metadata for the directory entry itself, not the total size of everything below it.

With no sorting option, entries are sorted alphabetically, and that default silently skips names beginning with a dot. A clean-looking listing is not proof that the directory holds no hidden files.

3. Include hidden entries when checking a directory

Use -a or --all to include names beginning with a dot. This also pulls in the implied . and .. entries:

$ vdir -la --time-style=long-iso /path/to/project
total 20
drwxr-xr-x 3 alice alice 4096 2026-09-27 17:24 .
drwxr-xr-x 8 alice alice 4096 2026-09-27 17:10 ..
-rw-r--r-- 1 alice alice   31 2026-09-27 17:22 .env.example
drwxr-xr-x 2 alice alice 4096 2026-09-27 17:24 src

-l is already the default for vdir, but writing it out makes the intent obvious if you later adapt the command for ls. --time-style=long-iso gives a predictable, sortable date and time for a human review, and does not touch the actual file timestamp.

If you want hidden names but not the implied dot entries, use -A or --almost-all. Treat .env, SSH-related files and other hidden names as potentially sensitive: listing them is harmless, but reading or copying their contents is a separate action with its own consequences.

4. List a directory entry instead of opening it

When the argument is a directory, the normal behaviour is to list its contents. Use -d or --directory when you want the directory's own metadata instead:

$ vdir -d --time-style=long-iso /path/to/project
drwxr-xr-x 3 alice alice 4096 2026-09-27 17:24 /path/to/project

Useful for checking permissions, ownership or the directory's own modification time without a second listing scrolling past. It is also a common script distinction: vdir directory inspects children, vdir -d directory inspects the named directory.

Checkpoint: use test -r /path/to/project and test -x /path/to/project if you need to tell read permission apart from permission to search a directory. A failed listing can be caused by a parent directory just as easily as by the target's own mode.

5. Make names and ordering easier to review

For one entry per line, use -1. To mark directories with a trailing slash, use -p, or classify several file types at once with -F:

$ vdir -1p /path/to/project
README.md
reports/
src/

Use -t for newest modification time first, then -r to reverse it, or -S for largest allocated size first. None of these change the files, only the order they appear in. For a directory-order view with no sorting at all, use -U; that order is filesystem-dependent, so do not treat it as stable across machines.

File sizes in a long listing are bytes by default. Add -h for readable units such as KiB and MiB. That is convenient for a human, poor for parsing, since the unit and column width both vary. For a script, reach for a machine-specific interface and validate its input rather than scraping a formatted long listing.

6. Inspect subdirectories recursively

Use -R or --recursive when you need everything below a directory, not just the top level:

$ vdir -R -1 /path/to/project
/path/to/project:
README.md
reports
src

/path/to/project/reports:
monthly.txt

/path/to/project/src:
main.c

Recursive output grows large fast. Start with a narrow path, and only add -a once hidden entries are actually part of the question. If a subdirectory cannot be read, vdir can still print the entries it can reach and return status 1 for the minor problem, so check the status explicitly when that matters:

$ vdir -R /path/to/project > /tmp/project-list.txt
$ status=$?
$ printf 'vdir exit status: %s\n' "$status"
vdir exit status: 0

Use a fresh temporary output path for a review. Shell redirection with > truncates an existing file before vdir even runs, so never point it at a report you might still need. If the listing turns out wrong, the source directory is untouched; remove or replace only the temporary report once you have checked it.

7. Diagnose the common traps

A missing path normally produces an error and a non-zero status. Check the spelling and the parent directory before reaching for privileges:

$ vdir /path/to/missing-directory
vdir: cannot access '/path/to/missing-directory': No such file or directory
$ printf 'exit status: %s\n' "$?"
exit status: 2
$ test -d /path/to/missing-directory || echo 'not a directory'
not a directory

Do not use sudo just to make a stuck command look successful. Elevated access can hide a real ownership or deployment problem, and it can expose names a service account was never meant to see. Use it only with an explicit administrative reason and a clear sense of the privacy boundary you are crossing.

Done means