首页 > Sysadmin > 正文

5 Ways to Get Just Filenames on Linux

2026-11-02 Sysadmin

This article focuses strictly on extracting filenames—no permissions, no timestamps, no extra metadata.

I. TL;DR: Choose by scenario

  • Basename only from a full path: basename /usr/bin/sort → sort.
  • Single-column listing in the current directory: ls -1, pipe-friendly.
  • Find specific types: find . -maxdepth 1 -name "*.log".
  • Names with spaces or newlines: find . -maxdepth 1 -type f -print0 | xargs -0 -I{} basename "{}".

II. basename: strip the directory

basename /usr/bin/sort
basename -s .h include/stdio.h
basename -a /var/log/syslog /etc/passwd

basename outputs only the final path component.[2] Add -s to also strip a suffix; add -a to accept multiple arguments and print one per line. It does not check whether the file exists, so it is safe to use on arbitrary strings.

Sample output:

sort
stdio
syslog
passwd

III. ls single-column and filtered output

ls -1
ls -1 *.conf
ls -F

ls defaults to a multi-column layout; add -1 (digit one) to force single-column output.[1] With shell globbing, the shell expands filenames before passing them to ls, so ls -1 *.conf shows only matching files. -F appends indicators: * for executables, / for directories, @ for symlinks. When reading filenames only, turn off colors with --color=never.

Sample output:

archive.tar.gz
regular.txt
script.sh

IV. find: filter by criteria

find . -maxdepth 1 -type f -name "*.log"
find . -maxdepth 1 -name ".*"

find traverses recursively by default; -maxdepth 1 restricts it to the current directory.[3] -name uses shell-style globbing, -type f limits to regular files, and -name ".*" finds hidden files. find prefixes results with ./; for bare filenames, add -printf '%fn'.

Sample output:

./regular.txt

V. Script safety: spaces and special characters

touch "file with spaces.txt" "weird$name.log"
ls -1
ls -b
find . -maxdepth 1 -type f -print0 | xargs -0 -I{} basename "{}"

When filenames contain spaces, newlines, or tabs, for f in $(find . -name "*.txt") splits on whitespace and produces incorrect results. The correct approach is to let find use NUL delimiters (-print0) and consume them with xargs -0.[3] ls -b converts non-printable characters into C-style escapes, which helps debugging.[1]

Sample output:

file with spaces.txt
weird.log

VI. Rollback, troubleshooting, and limitations

Troubleshooting

Symptom Cause Fix
find output includes ./ Default behavior Add -printf '%fn' or pipe through sed 's|^./||'
basename returns empty Input is a directory ending with / Run realpath first, or remove the trailing slash manually
ls -1 still shows multiple columns Output is being piped or redirected This is normal; pipes auto-single-column; check for aliases with alias ls
Script loses files with spaces Used for f in $(find ...) Switch to -print0 + xargs -0

Limitations

  • ls is a user-space program and does not list hidden files unless -a is explicitly added; admin scripts should not rely on ls parsing—use find or shell globs directly.
  • find . -maxdepth 1 may have poor performance on large directories with NFS mounts; limiting by absolute path is more stable.
  • basename and dirname perform string slicing only and do not verify path existence.
  • When filenames contain newline characters, even -print0 only guarantees find does not split output; downstream tools still need NUL support.

Test record

  • Environment: WSL2 Ubuntu 24.04, kernel 5.15, GNU coreutils 9.4, GNU findutils 4.9.0.
  • basename /usr/bin/sort → sort; basename -s .h include/stdio.h → stdio.
  • ls -1 auto-single-column in pipes; ls -F appends indicators.
  • find . -maxdepth 1 -type f -print0 | xargs -0 -I{} basename "{}" correctly prints filenames with spaces.
  • Filenames containing $ need quoting at touch; ls -b shows escaped forms.

References

Commands were verified on WSL Ubuntu (24.04) and cross-checked against Debian-family and upstream documentation.