How to list only files, not directories, sorted by size in Linux Bash shell

Strange that both the 𝚕𝚜 and the 𝚏𝚒𝚗𝚍 commands cannot do this on their own

In my book Linux Command-Line Tips & Tricks, I had mentioned a feature that was lacking in the ls command. In Microsoft Windoos or rather DOOS, you can type dir /ad and get a list of directories. You cannot do this in bash with just built-in parameters. You need to use a hack in the arguments, i.e., ls -d */. Its output also presents a wrinkle in that the directory names are suffixed by the slash. This makes it difficult to use the output ls command in loops.

The suggested alternative is find -maxdepth 0 -type d. This is obviously not succinct as the DOS command.

This is not the only shortcoming. ls cannot list only files. No sir. For that also, the alternative is find or rather find * -maxdepth 0 -type f.

For one of my scripts, I needed to iterate over a list of files sorted by file size. ls can do this but it will also list directories. find can list files alone but is deficient in the sorting department.

The solution is an indictment of two of the most basic commands in Linux Bash.

#!/bin/bash
set -u

# Directory name is read from the command line
sDir="$*"

if [ ! -d "$sDir" ]; then
  echo -e "ERROR:\tNot a directory — $sDir"
  exit
fi

# Get temporary file to store the list of names of files
sListFile=$(mktemp)

# Get absolute path of directory
sDir=$(readlink -f "$sDir")

pushd . > /dev/null
cd "$sDir"

# Generate the list and store it in the temp file
ls -1pr --sort=size | grep -v "/" > "$sListFile"

# Read the list line-by-line
while IFS= read -u 20 sLine ; do
  sFileName=$(basename "$sLine")
  sFile=$(readlink -f "${sDir}/${sFileName}")

  # Ignore non-file
  if [ ! -f "$sFile" ]; then
    continue 
  fi

  # Do whatever you want with the file name
  echo "$sFile"

done 20< "$sListFile"

# 20 is a randomly chosen number for the file descriptor
# from which the list is read

popd > /dev/null

You need to jump through all these hoops because some files have spaces and brackets that tend to trip ls, find and other bash commands and also wildcards * and ?.


Become a Linux command-line warrior by reading my book Linux Command-Line Tips & Tricks.

Book photo

Link: | Magic Link:

Comments are not enabled yet.

For older posts, check the archives.