I frequently download PDF files with heinous numeric file names from my browser. These automatically go into ~/Downloads. Ideally I would like to just be able to open these files with:

evince "the most recently modified file"

without having to open ~/Downloads to find the file name.

Is there a simple way to specify "the most recently modified file" in bash?

NOTE: I know that it is possible to do this, but ideally I am looking for a solution that would be simpler than ls -t'ing ~/Downloads to check the name.

  • 1
    There is no way to do this with bash that is both simple and foolproof. I believe zsh can do this with the *(om[1]) glob. – jw013 Mar 22 '12 at 15:11
evince "$(ls -t | head -n1)"

While it will handle spaces, tabs, and (I believe) printing specials, it will break if the filename contains a newline, and possibly on some other non-printing characters.

| improve this answer | |
  • This won't work for a lot of different files. – l0b0 Mar 22 '12 at 15:14
  • 1
    @l0b0 I am aware of the limitations of parsing ls, that's why I mentioned them. – Kevin Mar 22 '12 at 15:24
  • thanks, this is simple and will definitely work for my purposes (who the heck puts newlines in a filename!?) – DQdlM Apr 4 '12 at 14:05
  • @DQdlM: Hackers and people who test their code properly. – l0b0 Apr 4 '12 at 14:21
  • This is good enough for most simple cases. – Jon McClung Feb 28 '19 at 15:13

This is a more correct and robust approach than ls -t, at the cost of some additional complexity.


Add a short shell script (code below) to your $PATH. ~/bin is a good place for it.

Remember to make sure

  • the script is executable chmod +x ~/bin/script_name
  • ~/bin is in your $PATH


Pass the command you want to run on the newest file in ~/Download to last_download.


Assuming you named the script last_download

  • last_download (no arguments): runs evince, the default command, on the newest file in ~/Downloads
  • last_download mplayer: runs mplayer on the newest file in ~/Downloads
  • last_download cp -t ~/Desktop: copies the newest file in ~/Downloads to ~/Desktop


# Usage: last_download [cmd [options]...]


# default command
if [ $# -eq 0 ]; then
        set -- evince;

# find newest file
for f in "$dir"/*; do
        if [ -z "$newest" ] || [ "$f" -nt "$newest" ]; then
if ! [ -e "$newest" ]; then
        exit 1

# run command on newest file
"$@" "$newest"

Note: The script only looks in ~/Download but it would not be hard to generalize it to support any directory, in which case a name change would also be warranted.

| improve this answer | |
  • Well done, nice and thorough. – Kevin Mar 22 '12 at 16:01
  • 1
    ... except it puts the command to run outside your shell context, so it won't work with bash builtin commands, aliases, functions, anything set up in your bashrc, etc. – peth Mar 22 '12 at 16:48
  • @user112553 Yes that is a good point. However, it would be trivial to convert the script into a function if the user so desired. – jw013 Mar 22 '12 at 17:32
  • True. I just saw everyone else nitpicking and wanted my own nit. ;) – peth Mar 22 '12 at 17:56
  • @jw013 Sorry to ask (I'm a novice) but, how would you convert the script into a function so that it will recognize your aliases, etc? I tried: function last_file { source ~/scripts/last_file.sh } At the end of my .bashrc, but aliases were not preserved. – user1247 Mar 31 '12 at 12:49
exec zsh
evince ~/Downloads/*.pdf(om[1])

or if you don't want to switch to zsh

cd ~/Downloads
zsh -c 'evince ./*.pdf(om[1])'

The bits between parentheses are glob qualifiers. om changes the order on globs to use the modification time rather than the name (newest first). [1] means to use only the first match.

For more information, see this answer to "How do I filter a glob in zsh".

| improve this answer | |

You can use a modified find_date_sorted:

last_download() {
    while IFS= read -r -d '' -u 9
        cut -d ' ' -f 3- <<< "$REPLY"
    done 9< <(find ~/Downloads -maxdepth 1 -type f -printf '%TY-%Tm-%Td %TH:%TM:%TS %p\0' | sort -rz)

It'll work with any filenames. To open the file:

evince "$(last_download)"
| improve this answer | |
  • 1
    Actually this doesn't work for files with a newline in their name. – Kevin Mar 22 '12 at 15:29
  • @Kevin: Ah yes, because of head. My bad. Should be fixed now. – l0b0 Mar 22 '12 at 16:09
  • Even though file names ending in newlines are uncommon, it should be noted that command substitution strips trailing newlines, even when quoted. – jw013 Mar 23 '12 at 14:32
  • D'oh! You're right, of course. You'd have to use a trick to fix that. – l0b0 Mar 23 '12 at 14:39
  • Thanks for this answer, I always learn way more than I intend when I come on SE! – DQdlM Apr 4 '12 at 14:07

No, and even if there were, you couldn't be sure some system log won't usually be the most recently updated file.

Kevin's answer (he beat me to it) works if you just want to avoid manually opening ~/Downloads.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.