How to Sort Files in Natural Numerical Order Using “ls”

Sort File Names with Numbers Naturally using ls

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 in natural numerical 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 in Natural Numerical 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:

  1. 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.
  2. Press Enter.
    Sorting files with (version) numbers in their name naturally usng GNU ls

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):

  1. Type ls -1 | sort -V | column at a terminal prompt

    Mac: 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; and
    column 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.

  2. Press Enter.

    Sort filenames with numbers naturally in Mac Terminal using ls

How to Sort File Names with Numbers in Natural Numerical 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:

  1. Open the config file for your shell in a plain text editor.
    Mac: On macOS, you can use pico ~/.zshrc to edit your configuration file for the default shell; of course, you can also use another editor such as Vim.
  2. 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.
  3. Save the file and exit the editor.
  4. Run source ~/.<configuration file> to load the command.
    Mac: Type and run source ~/.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 with numbers naturally using “ls” tested with macOS Sonoma 14.0–14.2 and Ventura 13.4 as well as Fedora Linux 38; updated February 2024)

Home » Mac Tips and Resources » How to Sort Files in Natural Numerical Order Using “ls”