Search code examples
bashterminalio-redirectiontty

Bash capture output of command as unfinished input for command line


Can't figure out if this is possible, but it sure would be convenient.I'd like to get the output of a bash command and use it, interactively, to construct the next command in a Bash shell. A simple example of this might be as follows:

> find . -name myfile.txt
/home/me/Documents/2015/myfile.txt

> cp /home/me/Documents/2015/myfile.txt /home/me/Documents/2015/myfile.txt.bak

Now, I could do:

find . -name myfile.txt -exec cp {} {}.bak \;
or
cp `find . -name myfile.txt` `find . -name myfile.txt`.bak
or
f=`find . -name myfile.txt`; cp $f $f.bak

I know that. But sometimes you need to do something more complicated than just add an extension to a filename, and rather than getting involved with ${f%%txt}.text.bak etc etc it would be easier and faster (as you up the complexity more and more so) to just pop the result of the last command into your interactive shell command line and use emacs-style editing keys to do what you want.

So, is there some way to pipe the result of a command back into the interactive shell and leave it hanging there. Or alternatively to pipe it directly to the cut/paste buffer and recover it with a quick ctrl-v?


Solution

  • Typing M-C-e expands the current command line, including command substitutions, in-place:

    $ $(echo bar)
    

    Typing M-C-e now will change your line to

    $ bar
    

    (M-C-e is the default binding for the Readline function shell-expand-line.)


    For your specific example, you can start with

    $ cp $(find . -name myfile.txt)
    

    which expands with shell-expand-line to

    $ cp /home/me/Documents/2015/myfile.txt
    

    which you can then augment further with

    $ cp /home/me/Documents/2015/myfile.txt
    

    From here, you have lots of options for completing your command line. Two of the simpler are

    1. You can use history expansion (!#:1.txt) to expand to the target file name.
    2. You can use brace expansion (/home/me/Documents/2015/myfile.txt{,.bak}).