HACKER Q&A
📣 baobun

Extendable" Shell Commands?


I often find myself in the situation where I fire off a long-running process in the shell and then want to do something as a follow-up, at which point it is too late to add that '&& foo || bar' at the end of the line.

Simple example: Download this Linux ISO.. Oh, and flash it to my USB drive... Oh, and check the shasum... Oh, and show a notification when done.

Then the next time I want a slight variation of something more complex, every time I'm weighing the running time of the first process vs the time to type out or modify the second part.

I could open a separate shell and spawn a second process waiting for the first to finish but rarely worth the overhead of doing that.

So what I'd like is a "chainable shell" or "living prompt", where I can type out whatever comes next as the last shell command is already and still running in the foreground. Depending on the program, I noticed this kind-of already works where bash will actually go ahead and run whatever I type in the middle of the output of a blocking process once it's finished. But only for some programs.

Feels like something that hits most of us and should be possible to make something in bash/zsh for triggered by a keyboard shortcut. Yet I've never seen anything for this.

Anyone hacked together or found something like this that they use and would like to share?


  👤 baobun Accepted Answer ✓
Prompted by https://news.ycombinator.com/item?id=46231293 - piping from stdout/stderr would be extra cool but we only really need the exit code here.

👤 not_your_vase
Hack:

    long-running-command &
    pid_of_long_running_cmd=$(pidof long-running-command)
    tail --pid=$pid_pf_long_running_cmd -f /dev/null && forgotten-command
Tail quits when $pid_pf_long_running_cmd disappears, and kicks off the forgotten-command. (It won't know however the exit code of the original cmd, so that's a drawback)

👤 i15e
You can use Ctrl+z to suspend the foreground process, bg to resume it in the background, and then wait to wait for it to complete. By default wait will wait for all jobs to finish and then return a success exit code, however if you give it a specific job ID it will instead return the exit code of the waited-on process:

    $ (sleep 10; false)
    ^Z
    [1]+  Stopped                 ( sleep 10; false )
    $ wait %% && echo ok || echo nok
    [1]+  Exit 1                  ( sleep 10; false )
    nok