bash - automatically capture output of last execut

2019-01-03 11:55发布

I'd like to be able to use the result of the last executed command in a subsequent command. For example,

$ find . -name foo.txt
./home/user/some/directory/foo.txt

Now let's say I want to be able to open the file in an editor, or delete it, or do something else with it, e.g.

mv <some-variable-that-contains-the-result> /some/new/location

How can I do it? Maybe using some bash variable?

Update:

To clarify, I don't want to assign things manually. What I'm after is something like built-in bash variables, e.g.

ls /tmp
cd $_

$_ holds the last argument of the previous command. I want something similar, but with the output of the last command.

Final update:

Seth's answer has worked quite well. Couple of things to bear in mind:

  • don't forget to touch /tmp/x when trying the solution for the very first time
  • the result will only be stored if last command's exit code was successful

20条回答
萌系小妹纸
2楼-- · 2019-01-03 12:37

Disclamers:

  • This answer is late half a year :D
  • I'm a heavy tmux user
  • You have to run your shell in tmux for this to work

When running an interactive shell in tmux, you can easily access the data currently displayed on a terminal. Let's take a look at some interesting commands:

  • tmux capture-pane: this one copies the displayed data to one of the tmux's internal buffers. It can copy the history that's currently not visible, but we're not interested in that now
  • tmux list-buffers: this displays the info about the captured buffers. The newest one will have the number 0.
  • tmux show-buffer -b (buffer num): this prints the contents of the given buffer on a terminal
  • tmux paste-buffer -b (buffer num): this pastes the contents of the given buffer as input

Yeah, this gives us a lot of possibilities now :) As for me, I set up a simple alias: alias L="tmux capture-pane; tmux showb -b 0 | tail -n 3 | head -n 1" and now every time I need to access the last line i simply use $(L) to get it.

This is independent of the output stream the program uses (be it stdin or stderr), the printing method (ncurses, etc.) and the program's exit code - the data just needs to be displayed.

查看更多
一纸荒年 Trace。
3楼-- · 2019-01-03 12:38

There are more than one ways to do this. One way is to use v=$(command) which will assign the output of command to v. For example:

v=$(date)
echo $v

And you can use backquotes too.

v=`date`
echo $v

From Bash Beginners Guide,

When the old-style backquoted form of substitution is used, backslash retains its literal meaning except when followed by "$", "`", or "\". The first backticks not preceded by a backslash terminates the command substitution. When using the "$(COMMAND)" form, all characters between the parentheses make up the command; none are treated specially.

EDIT: After the edit in the question, it seems that this is not the thing that the OP is looking for. As far as I know, there is no special variable like $_ for the output of last command.

查看更多
一夜七次
4楼-- · 2019-01-03 12:39

I just distilled this bash function from the suggestions here:

grab() {     
  grab=$("$@")
  echo $grab
}

Then, you just do:

> grab date
Do 16. Feb 13:05:04 CET 2012
> echo $grab
Do 16. Feb 13:05:04 CET 2012

Update: an anonymous user suggested to replace echo by printf '%s\n' which has the advantage that it doesn't process options like -e in the grabbed text. So, if you expect or experience such peculiarities, consider this suggestion. Another option is to use cat <<<$grab instead.

查看更多
放我归山
5楼-- · 2019-01-03 12:42

As an alternative to the existing answers: Use while if your file names can contain blank spaces like this:

find . -name foo.txt | while IFS= read -r var; do
  echo "$var"
done

As I wrote, the difference is only relevant if you have to expect blanks in the file names.

NB: the only built-in stuff is not about the output but about the status of the last command.

查看更多
ゆ 、 Hurt°
6楼-- · 2019-01-03 12:44

This is not strictly a bash solution but you can use piping with sed to get the last row of previous commands output.

First lets see what i have in folder "a"

rasjani@helruo-dhcp022206::~$ find a
a
a/foo
a/bar
a/bat
a/baz
rasjani@helruo-dhcp022206::~$ 

Then, your example with ls and cd would turn to sed & piping into something like this:

rasjani@helruo-dhcp022206::~$ cd `find a |sed '$!d'`
rasjani@helruo-dhcp022206::~/a/baz$ pwd
/home/rasjani/a/baz
rasjani@helruo-dhcp022206::~/a/baz$

So, the actual magic happens with sed, you pipe what ever output of what ever command into sed and sed prints the last row which you can use as parameter with back ticks. Or you can combine that to xargs also. ("man xargs" in shell is your friend)

查看更多
戒情不戒烟
7楼-- · 2019-01-03 12:45

You could set up the following alias in your bash profile:

alias s='it=$($(history | tail -2 | head -1 | cut -d" " -f4-))'

Then, by typing 's' after an arbitrary command you can save the result to a shell variable 'it'.

So example usage would be:

$ which python
/usr/bin/python
$ s
$ file $it
/usr/bin/python: symbolic link to `python2.6'
查看更多
登录 后发表回答