RD Ward
RD Ward

Reputation: 6737

How can I pass input to output in bash?

I am trying to streamline a README, where I can easily pass commands and their outputs to a document. This step seems harder than I thought it would be.

I am trying to pass the input and output to a file, but everything I am trying just either displays echo test or test

The latest iteration, which is becoming absurd is:

echo test | xargs echo '#' | cat <(echo) <(cat -) just shows # test

I would like the results to be:

echo test

# test

Upvotes: 0

Views: 263

Answers (2)

Gordon Davisson
Gordon Davisson

Reputation: 125798

You can make a bash function to demonstrate a command and its output like this:

democommand() {
    printf '#'
    printf ' %q' "$@"
    printf '\n'
    "$@"
}

This prints "#", then each argument the function was passed (i.e. the command and its arguments) with a space before each one (and the %q makes it quote/escape them as needed), then a newline, and then finally it runs all of its arguments as a command. Here's an example:

$ democommand echo test
# echo test
$ democommand ls
# ls
Desktop     Downloads   Movies      Pictures    Sites
Documents   Library     Music       Public

Now, as for why your command didn't work... well, I'm not clear what you thought it was doing, but here's what it's actually doing:

  • The first command in the pipeline, echo test, simply prints the string "test" to its standard output, which is piped to the next command in the chain.
  • 'xargs echo '#'takes its input ("test") and adds it to the command it's given (echo '#') as additional arguments. Essentially, it executes the commandecho '#' test`. This outputs "# test" to the next command in the chain.
  • cat <(echo) <(cat -) is rather complicated, so let's break it down:
    • echo prints a blank line
    • cat - simply copies its input (which is at this point in the pipeline is still coming from the output of the xargs command, i.e. "# test").
    • cat <(echo) <(cat -) takes the output of those two <() commands and concatenates them together, resulting in a blank line followed by "# test".

Upvotes: 1

that other guy
that other guy

Reputation: 123470

Pass the command as a literal string so that you can both print and evaluate it:

doc() { printf '$ %s\n%s\n' "$1" "$(eval "$1")"; }

Running:

doc 'echo foo | tr f c' > myfile

Will make myfile contain:

$ echo foo | tr f c
coo

Upvotes: 1

Related Questions