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.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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.
Method 2
This is a more correct and robust approach than ls -t, at the cost of some additional complexity.
Setup
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 ~/binis in your$PATH
Usage
Pass the command you want to run on the newest file in ~/Download to last_download.
Examples
Assuming you named the script last_download
last_download(no arguments): runsevince, the default command, on the newest file in~/Downloadslast_download mplayer: runsmplayeron the newest file in~/Downloadslast_download cp -t ~/Desktop: copies the newest file in~/Downloadsto~/Desktop
Code
#!/bin/sh
# Usage: last_download [cmd [options]...]
newest=
dir=~/Downloads
# default command
if [ $# -eq 0 ]; then
set -- evince;
fi
# find newest file
for f in "$dir"/*; do
if [ -z "$newest" ] || [ "$f" -nt "$newest" ]; then
newest="$f"
fi
done
if ! [ -e "$newest" ]; then
exit 1
fi
# run command on newest file
"<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="062246">[email protected]</a>" "$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.
Method 3
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”.
Method 4
You can use a modified find_date_sorted:
last_download() {
while IFS= read -r -d '' -u 9
do
cut -d ' ' -f 3- <<< "$REPLY"
break
done 9< <(find ~/Downloads -maxdepth 1 -type f -printf '%TY-%Tm-%Td %TH:%TM:%TS %p' | sort -rz)
}
It’ll work with any filenames. To open the file:
evince "$(last_download)"
Method 5
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.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0