Got enough of looking for “file_10” in between “file_1” and “file_2” instead of after “file_9”? Find out here how to have “ls” on the command line (Linux or Mac) sort file names by number in natural order (and not resort to leading with zeros—file_01, etc.).
First, Going for Silver
Most participants at the first Olympic Games of the modern era in Athens 1896 had their sighs firmly set, I’d wager, on the silver medal.
For while athletes in second place got copper medals, the winners received the Olympic diploma, an olive branch and—a silver medal. (Only the first and second placed were rewarded with prices.)
Now, all those years later (and no matter the color scheme), is your directory listing on the console confused about what comes first, file_10 or file_2? There’s help, even without renaming files:
How to Sort File Names with Numbers by Number in Natural Order Using “ls”
Using GNU ls (e.g, Linux)
To sort filenames that contain numbers in a natural order (so you get log_1, log_2, …, log_10 instead of log_1, log_10, log_2, …) on Linux and other systems using GNU ls:
- Type
ls -v
at a terminal prompt in the folder whose files you want to list.
Here’s why: The-v
option (for “version”) has ls sort numbers in naturally ascending order, not lexicographically even within file names.
Reverse: You can add-r
to reverse the sorting order; this will also reverse number sorting, so files will be listed in descending order. - Press Enter.
Using BSD ls (e.g., FreeBSD and macOS)
Time needed: 1 minute
To list files in a directory alphabetically and also by natural number using a BSD flavor of Unix (such as OpenBSD, FreeBSD or macOS a Mac):
- Type
ls -1 | sort -V | column
at a terminal promptMac: You can open Terminal right in the folder you want to list.
Here’s why:ls -1
lists files each on one line (which should be the default for passing it on to another program);|
takes that listing and sends it to the sort command as an input;sort -V
sorts input in alphabetical order and version numbers for files in natural ascending order; andcolumn
makes output use the width of the terminal with multiple columns like ls does.
Reverse: Append -r to the end to reverse sorting so files are sorted by reverse alphabetical order and descending numerical order. - Press Enter.
How to Sort File Names with Numbers by Number in Natural Order Using “ls”: FAQ
Can I use the “-v” argument or “sort -V” with other ls options?
Yes.
Barring where combining two options is impossible because they contradict each other, you can combine sorting numbers naturally with other ls options.
Example: ls -la | sort -V | column
will show all files including information those files, all sorted naturally by file name.
Can I make natural numerical order the default for “ls”?
Yes; you can either set up a shortcut (shell alias) for naturally sorted listing or set up a function that performs the desired operation silently passing on arguments to the native ls.
To add an alias to your shell for ls with natural version sorting:
- Open the config file for your shell in a plain text editor.
Mac: On macOS, you can usepico ~/.zshrc
to edit your configuration file for the default shell; of course, you can also use another editor such as Vim. - Add the following line to the file at the bottom:
alias ll='ls -1 | sort -V | column'
Other names: You can pick any name for your command (instead of ll in this example); make sure it does not clash with any existing commands, as it will take precedence.
Overwriting ls: You can also overwrite the ls command itself; to use ls with any other options, use\ls
or/bin/ls
to avoid invoking the alias.
Example: /bin/ls -a will run the ls command with the option -an even if ls is configured to run the command above. - Save the file and exit the editor.
- Run
source ~/.<configuration file>
to load the command.
Mac: Type and runsource ~/.zshrc
on a Mac, for example.
A custom ls that just does the right natural thing
To set up a custom ls function for zsh on macOS as an example:
- Add the following code to the ~/.zshrc file (in place of the alias command), otherwise following the steps above.
function ls() {
# set to the column number for filenames on long ls output (ls -l)
local FILENAME_COLUMN=9
# set to the column number for filenames on number of blocks output (ls -s)
# (total size will move depending on sorting)
local BLOCKS_COLUMN=1
# set to true to add the -f argument to ignorei case when sorting; this
# overrides the standard argument -f for unsorted ouput
local ADD_IGNORE_CASE=true
# all ls options that change sorting order
local SORTING_OPTIONS="St"
local all_args=("$@")
local dash_args=()
local i
for ((i=1; i<${#all_args[@]}+1; i++)); do
if [[ "${all_args[$i]}" == -* ]]; then
dash_args+=(${all_args[$i]})
if [[ $ADD_IGNORE_CASE == true && "${all_args[$i]}" == -*f* ]]; then
all_args[$i]=$(echo "${all_args[$i]}" | sed 's/f//')
if [[ "${all_args[$i]}" == - ]]; then
all_args[$i]=""
fi
fi
fi
done
if [[ $dash_args[@] =~ [$SORTING_OPTIONS] ]]; then
/bin/ls $@
elif [[ $ADD_IGNORE_CASE == false && $dash_args[@] =~ f ]]; then
/bin/ls $@
else
local reverse=""
if [[ $dash_args[@] =~ r ]]; then
reverse="-r"
fi
local long=""
if [[ $dash_args[@] =~ l ]]; then
long="-k$FILENAME_COLUMN"
fi
local blocks=""
if [[ $dash_args[@] =~ s ]]; then
blocks="-k$BLOCKS_COLUMN"
fi
local ignore_case=""
if [[ $ADD_IGNORE_CASE == true && $dash_args[@] =~ f ]]; then
ignore_case="-f"
fi
/bin/ls -1 $all_args | sort -V $reverse $long $blocks $ignore_case | column
fi
}
You can download the ladedu_ls script as well, of course, and include it (after you have examined its code) in your .zshrc with the following line:
source <path_to_ladedu_ls.zsh>
Note that this ls function does not deal specially with cases like -ft
, where a sorting option (such as -t
) is used together with the option that offers unsorted output, -f
. These are passed on to ls as is.
Can I use GNU ls on a Mac or other system?
Typically yes.
On a Mac, you can install GNU coreutils using Homebrew; on other systems you can likely also install a version of GNU coreutils and use ls -v
as described above.
What if all I have is lexicographic sorting?
You can always resort to naming files with leading zeros, of course. Instead of ladedu_1.log, ladedu_2.log, …, ladedu_10.log, you can use the file names ladedu_001.log, ladedu_002.log, …, ladedu010.log. This also has all filenames assume the same length.
(How to sort file names by number in natural order using “ls” tested with macOS Sonoma 14.0–14.5 and Ventura 13.4 as well as Fedora Linux 38; first published August 2023, last updated July 2024)