Bash – Quick way to open results from `find` or `locate`

bashfindlocate

When I run find or locate, the matching files will populate stdout, one file per line. The next step is often that I want to open one of these files. This would be faster and more efficient if I did not have to type out the entire file path, but simply could interact with the search results somehow. Which is the fastest way to open a file displayed in the search results?

Solutions like those given in Open a result of `locate` with `vi`, How to `locate` multiple files and open them in vim?, and How can I act on the results of the "locate" command? require typing out a rather long second command, which is not as fast as I would like.

Instead, is there a way to, for example, automatically assign each file from the search result to a numerical variable name (s1 – sn), so that to open the first result I would simply type vi $s1? Or is a better solution to this problem to use a fuzzy finder like fzf or fasd?

Best Answer

I've had this in my ~/.screenrc for a while:

bind -c pasteline 1 eval copy 'stuff "-Y"' 'paste .'
bind -c pasteline 2 eval copy 'stuff "2-Y"' 'paste .'
bind -c pasteline 3 eval copy 'stuff "3-Y"' 'paste .'
bind -c pasteline 4 eval copy 'stuff "4-Y"' 'paste .'
bind -c pasteline 5 eval copy 'stuff "5-Y"' 'paste .'
bind -c pasteline 6 eval copy 'stuff "6-Y"' 'paste .'
bind -c pasteline 7 eval copy 'stuff "7-Y"' 'paste .'
bind -c pasteline 8 eval copy 'stuff "8-Y"' 'paste .'
bind -c pasteline 9 eval copy 'stuff "9-Y"' 'paste .'
bindkey ¬ command -c pasteline

Basically, typing ¬1 from within screen, inserts the first line above the cursor, ¬2 the second line and so on.

In my ~/.Xdefaults, I also have:

XTerm.VT100.translations:             #override\
    Meta <KeyPress> /: dabbrev-expand()

Which lets xterm complete (upon Alt+/) on what's on the screen (looking backward from the cursor position).

With zsh, when used within screen, you could do:

copy-screen() {
  screen -X eval copy 'stuff "-$ H\r"' 'writebuf .lastoutput'
  killring=(${(Oaf)"$(<~/.lastoutput)"})
  CUTBUFFER=$killring[1]
  killring[1]=()
}
zle -N copy-screen
bindkey '\ec' copy-screen

to bind Alt+C to that widget that stores the lines above the cursor into the cut buffer and the kill ring (what you paste with Ctrl+Y and cycle through with Alt+Y in emacs mode). (the above assumes screen was started from your home directory).

If the inserted text needs to be quoted (because it contains spaces or other special shell characters for instance), you can type Alt+" for zsh to quote it.

As an example, you've just run:

$ find /usr/local -size +1M
/usr/local/lib/liblzma.a
/usr/local/share/doc/sudo/ChangeLog
/usr/local/share/perl/5.18.2/Unicode/Unihan/Definition.db
/usr/local/share/perl/5.18.2/Unicode/Unihan/RSKangXi.db
/usr/local/share/perl/5.18.2/Unicode/Unihan/IRG_TSource.db
/usr/local/share/perl/5.18.2/Unicode/Unihan/HanYu.db
/usr/local/share/perl/5.18.2/Unicode/Unihan/RSUnicode.db
/usr/local/share/perl/5.18.2/Unicode/Unihan/IRG_GSource.db
/usr/local/share/perl/5.18.2/Unicode/Unihan/IRGKangXi.db
/usr/local/share/perl/5.18.2/Unicode/Unihan/IRGHanyuDaZidian.db    

And you want to open vim on that sudo ChangeLog above. With the first approach you'd type:

vim ¬9

With the second approach:

vim /usAlt+/

And repeat that Alt+/ until you get to the changelog.

With the third approach:

vim Alt+CCtrl+YAlt+Y

And repeat that Alt+Y until you get to the changelog.

The last approach can be used for your $s1 query.

Instead of storing in the killring array, store in an array (like $s) and use $s[1] for the first line, $s[2] for the second...

copy-screen() {
  screen -X eval copy 'stuff "-$ H\r"' 'writebuf .lastoutput'
  s=(${(Oaf)"$(<~/.lastoutput)"})
}
zle -N copy-screen
bindkey '\ec' copy-screen

That Alt+C stores the lines above the cursor in the s array.

In any case, what we're retrieving is what is displayed on the screen, which is not necessarily the same as what the last command output. For instance printf 'a\bc \n' outputs 5 bytes a, BS, c, SPC and LF, but displays just a c.

Related Question