13

I have a process which creates text files whose filenames are based on the timestamp of their moment of creation:

$ ls
1378971222.txt
1378971254.txt
1378971482.txt
1378971488.txt
1378972089.txt
1378972140.txt
1378972141.txt
1378972153.txt
1378972155.txt
1378972241.txt

How might I auto-complete the filename of the latest created file, i.e. the file with the latest mtime? There is no way to use Tab-completion for these files as almost every character in the filename is shared with another file. I am hoping to find a shortcut (such as Alt . which autocompletes the last argument of last command). I have managed to concoct the following alias which is great for VIM, but I would love to know if a general-purpose shortcut exists that I could use with kde-open, sqlite3, and other applications.

alias lastest="vim `ls -t | grep -vE "^total [0-9]*$" | head -n1`"
  • Having read all that, the question seems to have no satisfactory answer yet on how to have a keyboard shortcut to insert latest filepath (a la bash completion, and hopefully, also cycle through in chronological order) in the bash shell? – Roman Susi May 8 '17 at 4:42
  • @RomanSusi: This closest answer is by Weidenrinde, but it only inserts a literal $(ls -t|head -1) into the line. Therefore, no cycling. In absence of a satisfactory answer, I accepted the answer which taught me the most and provides the most utility. – dotancohen May 8 '17 at 5:40
  • Sure. It just occured to me it could be a cool shell feature, and wondered why nobody yet implemented it. – Roman Susi May 8 '17 at 17:48
6

Just remove the vim from the alias. Do something like this:

alias latest='ls -tr | tail -n 1'

You can then use any program to open the latest files:

emacs `latest`
ls `latest`
mv `latest` ../

etc.

However, this will break if your file names have spaces or weird characters which is why you should never parse ls. A better way would be something like this (add this to your .bashrc) :

function latest(){
  $1 "$(find . -type f -printf "%C@ %p\n" | sort | tail -n 1 | cut -d " " -f 2-)"
}

This function will execute whatever command you give it as an argument and pass the result of the find call (the latest file) to that command. So, you can do things like:

latest emacs
latest less

If you need to be able to do things like mv $(latest) foo/ try this one instead:

function latest(){
   A=(${@})
   prog=$1;
   lat=$(find . -type f -printf "%C@ %p\n" | sort | tail -n 1 | cut -d " " -f 2-)
   if [ ! -z $2 ] ; then 
     args=${A[@]:1}; 
     $prog "$lat" "${A[@]:1}"
   else
     $prog "$lat"
   fi
}

Then, to copy the latest file to bar/, you would do

latest cp bar

And you can still do latest emacs in the same way as before.

  • Thank you, there are quite a few things that I can learn here. – dotancohen Sep 13 '13 at 7:26
  • I'd recommend alias latest='\ls -tr | tail -n 1' - this will work if you have ls aliased. – domen Sep 27 '18 at 7:59
5

You can easily configure this in zsh, e.g. with something like this:

zstyle ':completion:*' file-sort date

(you can also change the line such that this style is only used for certain file name patterns)

zsh is very similar to bash, you could probably call it a superset of bash - feature-/usage-wise.

But perhaps bash has a similar feature.

  • Thanks, this is great. For a few reasons I prefer not to move to zsh but if I ever do, I have this bookmarked! – dotancohen Sep 13 '13 at 7:25
  • Thank you for introducing me to zsh! – dotancohen Jun 24 '14 at 17:52
3

Since the newest file is also sorted last, you could use menu-complete-backward. menu-complete and menu-complete-backward cycle through completions or insert the first or last completion. I have bound them to option-tab and shift-tab in ~/.inputrc:

"\e\t": menu-complete
"\e[Z": menu-complete-backward

Your terminal emulator might not insert \e[Z when you press shift-tab. Use C-v or cat -v to see what text is inserted when you press a key combination.

  • In fact, files are sorted alphabetically, not chronologically. If I figure out how to sort chronologically then I'll update with the info. – dotancohen Oct 5 '16 at 15:11
2

The background for the question is the speed of usage. I find a keyboard macro most appropriate. Add to ~/.inputrc:

# Alt-L --> newest file in directory
"\el": "$(ls -t|head -1)"

Further ideas: Originally, I wanted something that gives me the 1st, 2nd, 3rd newest file. An idea would be, to mark the places with a token, e.g. "grep x _", then execute a keyboard macro "\C-alatest-expansion \C-m" and "latest-expansion" prompts a curses-selection list to pick from the latest files for each " _ " token in the command line.

I consider this an important question, because one remaining advantage of GUI over SHELL is for me the selection of recently used/created files and directories. autojump helps a bit for directories, a solution for files is missing.

  • Thank you, that is helpful. Note that it inserts a literal $(ls -t|head -1) into the bash line, so it needs to be interpreted. That makes it less useful, but it is still a nice trick. – dotancohen Oct 29 '16 at 20:34

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.