Bash Command Line – Capture and Use Last or Nth Line in stdout

bashcommand line

Query

I use Bash. When I'm looking for files, often I'll do the following:

find -name stackexchange.hs

And often the results will look like:

/youre/the/man/now/dog/stackexchange.hs
/you/are/no/longer/the/dog/dog/stackexchange.hs
/this/is/the/file/i/want/stackexchange.hs

Then I'll want to do one of the following:

  • Option 1: Open the last item in the list of results in vim.
  • Option 2: Open the Nth item in the list of results in vim.

Currently, I cut-and-paste with the mouse. Which brings me to my question:

  1. Is there an easy, one-liner to accomplish options 1&2? Note that this is occurring after the find command.
  2. Is there a way to capture N-lines from stdout in some kind of bash vector/array?

Ideal usage

$ find -name am_i_really_all_alone.txt
./borges/library/you_are_not_alone.txt
./borges/library/am_i_really_all_alone.txt
$ vim (N)

(syntax and semantics may differ, but you get the point)

Similaria

There seem to be several similar questions. Here are my perceived differences (I am open to enlightenment):

Thank you for your help! Having used *nix/BSD when I was a teenager in the 90s and getting scared away by calling my burnout, acid-head neighbour to help me install drivers for my plug-and-play sound card, I'm relieved to discuss command-line minutiae with (perceivably) less frightening individuals. It feels good to be back.

Best Answer

Here is a potential solution to your issue that should be reasonably (but not perfectly) safe in the presence of funky file names (doesn't handle filenames with linefeeds in them - probably fixable, but there might be other problems lurking).

Two functions, the first one runs find with the parameters you pass it, saves the output in an array, and displays them. The second is just a helper to access that array.

myfind() {
  IFS=$'\n' __last_find_result=($(find "$@"));
  printf "%s\n" "${__last_find_result[@]}";
}
myget() {
  echo "${__last_find_result[$1]}";
}

Use case:

$ myfind . -name "c*"
./a b/c d
./.git/config
./.git/hooks/commit-msg.sample
$ vim "$(myget 0)"
# This opens the "./a b/c d" file.
$ vim "$(myget 2)"
# This opens ".git/hooks/commit-msg.sample"

Quotes not required around the $(myget index) if you don't have whitespace or other troublesome characters in your filenames.
Pushes the whole output of find to your environment, which might be limited. (Using a temporary file rather than that array would solve that, but has other issues - notably concurrent use from multiple shells.)