3

Sometimes the output of some command include other commands. And I'd like to start that command from output without using a mouse. For example, when command is not installed there is a message with line for installing this command:

$ htop
The program 'htop' is currently not installed. You can install it by typing:
sudo apt-get install htop

So. There I'd like to type a command, that will start the command from last line from output of htop. How it can be done?

Edit: I'll try show what I mean. There are two lines in "output" of command htop (actually, it's an error message). Second line of this message is the command sudo apt-get install htop. So I'd like to extract second line from output, and start it's like command itself. The following is a rubbish but it shows what I mean:

htop | tail -1 | xargs start_command
4
  • Which part of the command will you want to run? In this particular example, the output is an error message (printed to standard error) and you would need to somehow parse it. I don't see how we can give you a general answer since the part of the command's output (or error as in this case) you are interested will always be different.
    – terdon
    Jan 20, 2014 at 16:38
  • good point, in principle I ask myself why this is - the message shows the system knows how to solve the problem. But instead of solving it it tells you how to solve it. The system should respond "The program 'htop' is currently not installed. Installing it will take XXX bytes. Do you want me to install it?". Jan 20, 2014 at 16:48
  • If you are planning an auto command installer, you can make a wrapper for command execution that would tee the actual command to a unique and known file and just after that apply the execution of tail -1 THE_FILE if the line starts with 'sudo apt-get install'. However maybe would not be a good idea.
    – 41754
    Jan 20, 2014 at 16:50
  • This is a bad example and it should NEVER be done IMO. But I will try to answer in general below.
    – coteyr
    Jan 20, 2014 at 17:07

4 Answers 4

4

The right thing to do here is to set up bash to prompt for installation, as explained in SamK's answer. I'll answer strictly from a shell usage perspective.

First, the text you're trying to grab is on the command's standard error, but a pipe redirects the standard output, so you need to redirect stderr to stdout.

htop 2>&1 | tail -1

To use the output of a command as part of a command line, use command substitution.

$(htop 2>&1 | tail -1)

The result of the command substitution is split into words and each word is interpreted as a wildcard pattern. Here this happens to do the right thing: this is a command line with words separated by spaces, and there are no wildcard characters.

To evaluate a string as a shell command, use eval. To treat the result of the command as a string rather than a list of wildcard patterns, put it in double quotes.

eval "$(htop 2>&1 | tail -1)"

Of course, before evaluating a shell command like that, make sure it's really what you want to execute.

4

It is usually a bad idea to write scripts based on error message (think about localization for example). You should use exit codes instead

In your case I found the answer here from Gerhard Burger.

I Quote:


The package that is responsible for this behavior is the command-not-found Install command-not-found package, and it already includes the desired behavior although it is disabled by default. You can enable it by adding the following line to your ~/.bashrc

export COMMAND_NOT_FOUND_INSTALL_PROMPT=1

Now the behavior is changed to

The program 'x' is currently not installed. You can install it by typing:
sudo apt-get install x
Do you want to install it? (N/y)
1

If using GNU screen, add this to you ~/.screenrc:

bind R eval copy "stuff kY" "paste ."

Then you can press Ctrl-AR to insert the content of the line above the cursor.

0

With bash or more shells this os very easy to do if you know the output format. There are several ways to run out put as commands but the ones I like the best rely on variable expansion.

#!/bin/bash

CMD=`some/exeutible | parse output with something | and maybe something else`
`$CMD`

The ` says basicly "execute whats between ` and ` and will execute stored commands.

In your example you need parse the stderr and output then stock the parsed output between ` and `. I won't tell you how to parse the output, but take a look at This it should help with expansion.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .