[sf-lug] A shell script for listing files in order of modification time

John Magolske listmail at b79.net
Wed Apr 17 08:08:40 PDT 2013

Hi all,

Below is a shell script I wrote for the purpose of listing files
in a directory, sorted chronologically by modification time. This
started out as an alias for ls to display some number of most recently
modified files in chronological order. I don't recall everything I
tried, but at one point it had evolved into something like:

  ls -ldtr --color=always --quoting-style=literal `ls -tra | tail --lines=235`

but that can't deal with filenames with spaces in them...probably
there's a way to get that working, but I then decided to use find(1)
(which offered more options anyway), in a script that could:

- optionally recurse n levels into subdirectories
- adjust how far into the past to search
- display output colorized via the LS_COLORS environment variable
- list files even if they have messed up filenames with spaces,
  non-standard characters, etc.

I'm calling this fmf (find modified files). To provide an indication
of what was "found", the find portion of the command is shown in the
prompt of the less pager, as well as in stdout after quiting less.

One additional feature I'd really like to implement would be to have
the entire command pipeline expanded and placed into shell history,
such that after running the script one could just hit the up arrow
and have a nicely constructed command available for tweaking in many
directions beyond what the simplified wrapper script makes available.
Such that for example this:

  fmf ~/bin 31 1

would expand to this:

  find /home/john/bin -maxdepth 1 -type f -mtime -31 -print0 | xargs -0 ls -odtr --color=always | less -FRiCX -PM%E +G

and be placed in history as the previous command. Is there a shell way
of doing this? All I can think of is using tmux and its paste-buffer
command (equivalent to screen's "stuff" command) to "paste" the
command into the terminal. Or running sed against my ~/.zsh_history
file to swap out the "fmf" command with the fully expanded command
pipeline...but I'm hoping for a more elegant & portable solution.

In any case, here's the script. Any comments or suggestions are most
welcome. Note that in the line that reads LESS_TERMCAP_so='^[[0;36;40m'
the ^[ is not two characters, but a single control character created by
pressing "Ctrl-V" then the "Esc" key. I don't think escape characters
can be passed through email. Hmmm, let's try...
two characters: ^[
single Esc control character: 




# Last edit: 2013/03/25 Mon 8:34 PDT
# Copyright (c) 2013 John Magolske, 3-Clause BSD.

# Is the first argument an integer?
[ $1 -ne 0 -o $1 -eq 0 2> /dev/null ] && int="y" || int="n"

# If the first argument is NOT an integer it defines the directory to search,
# otherwise search the working directory. Other integer arguments define depth
# of search & modification time. Up to 3 arguments total can be input.
[ "$#" -eq 0 ]               && dir=`pwd` && days="14" && deep=""
[ "$#" -eq 1 -a $int = "y" ] && dir=`pwd` && days="$1" && deep=""
[ "$#" -eq 1 -a $int = "n" ] && dir="$1"  && days="14" && deep=""
[ "$#" -eq 2 -a $int = "y" ] && dir=`pwd` && days="$1" && deep="-maxdepth $2"
[ "$#" -eq 2 -a $int = "n" ] && dir="$1"  && days="$2" && deep=""
[ "$#" -eq 3 ]               && dir="$1"  && days="$2" && deep="-maxdepth $3"
[ "$#" -gt 3 ] && echo \
"You've input $# arguments, but $0 accepts a maximum of 3 arguments." && exit 1

# Adjust prompt color (ref: http://www.jukie.net/~bart/blog/less-colours )

# The find command used here
findcommand="find $dir "$deep" -type f -mtime -$days -print0"

# VISUAL environment variable = name of editor, only variable that can display
# in LESS prompt. No need for an editor here so use it to display find command.

# Run the find command and pipe it through the ls command, then the less pager
$findcommand | xargs -0 ls -odtr --color=always | less -FRiCX -PM%E +G

# Display the find command used
echo $VISUAL

John Magolske

More information about the sf-lug mailing list