Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash edit-and-execute-command echo

Tags:

bash

When I run the following one line loop, I get the expected output.

for index in $(seq 1 5) ; do echo "$(date +"%Y%m%d" -d "20160301 $index day")"; done
20160302
20160303
20160304
20160305
20160306

But when I use bash's edit-and-execute-command (control-x, control-e) and enter the same one line loop, I get output with unexpected commands echoed throughout.

for index in $(seq 1 5) ; do echo "$(date +"%Y%m%d" -d "20160301 $index day")"; done
seq 1 5
date +"%Y%m%d" -d "20160301 $index day"
20160302
date +"%Y%m%d" -d "20160301 $index day"
20160303
date +"%Y%m%d" -d "20160301 $index day"
20160304
date +"%Y%m%d" -d "20160301 $index day"
20160305
date +"%Y%m%d" -d "20160301 $index day"
20160306

I have export EDITOR=vim in my .bash_profile.


Update with more complicated example in response to comment from @l'L'l

I am using sub-shells because the real command is doing a fair bit more..

for index in $(seq 1 10) ; do td=`date +"%Y%m%d" -d "20160301 $index day"`; echo "$td: $(grep "$td" *gprs.csv | wc -l)" ; done

As with the simpler example, pasting into the command line is OK, but using edit-and-execute-command gives lots of echos in between.

I have already moved past this by using a script (because naturally enough the issue became even more complicated), but I am still interested to know if there an easy fix for this (edit-and-execute-command doesn't seem so useful if the output is not clear).

like image 416
Robert Mark Bram Avatar asked Aug 11 '16 05:08

Robert Mark Bram


1 Answers

Bash turns on the v flag before evaluating contents of the temporary file:

/* Turn on the `v' flag while fc_execute_file runs so the commands
   will be echoed as they are read by the parser. */
begin_unwind_frame ("fc builtin");
add_unwind_protect ((Function *)xfree, fn);
add_unwind_protect (unlink, fn);
add_unwind_protect (set_verbose_flag, (char *)NULL);
echo_input_at_read = 1;

retval = fc_execute_file (fn);
run_unwind_frame ("fc builtin");

The commands are printed to the standard error descriptor. As it turns, we can not control it via the standard interface.

But it is possible to source the file within the $EDITOR, then terminate the editor's process:

#!/bin/bash -
vim "$@"

if [[ "$(basename "$1")" =~ bash-fc-[0-9]+ ]]; then
  # Looks like edit-and-execute (C-x C-e)

  # The user has finished editing the temporary file.
  # It's time to evaluate the contents.
  source "$1"

  # Save current process ID for the subshell below.
  pid=$PID

  # The subshell helps to suppress the `Terminated` message.
  ( kill $pid >/dev/null 2>&1 )
fi

The commands will no longer be displayed after overriding the $EDITOR variable:

export EDITOR="/path/to/the-wrapper"
like image 178
Ruslan Osmanov Avatar answered Sep 19 '22 06:09

Ruslan Osmanov