Tell me more ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

In bash, when running with the -x option, is it possible to exempt individual commands from echoing?

I'm trying to make the output as neat as possible, so I am running certain parts of my script in a subshell with set +x. However, the row set +x itself is still echoed and adds no valuable information to the output.

I remember back in the bad old .bat days, when running with echo on, individual lines could be exempted by starting them with a @. Is there any equivalent in bash?

#!/bin/bash -x

function i_know_what_this_does() {
  (
    set +x
    echo do stuff
  )
}

echo the next-next line still echoes 'set +x', is that avoidable?
i_know_what_this_does
echo and we are back and echoing is back on

When running the above, output is:

+ echo the next-next line still echoes 'set +x,' is that 'avoidable?'
the next-next line still echoes set +x, is that avoidable?
+ i_know_what_this_does
+ set +x
do stuff
+ echo and we are back and echoing is back on
and we are back and echoing is back on
share|improve this question
1  
Please forget .bat! Shell has nothing common with so-called batch files. – F. Hauri Jan 2 at 9:22
2  
This is not an ideological purity debate. I was just giving a concrete example of exactly what I am looking for, using an environment familiar to many. I wouldn't say the DOS shell has "nothing" to do with unix shells, altough it is more primitive by far. – clacke Jan 2 at 9:56
1  
This was not an ideologic assetion! What you've learned before must be forgotten in order to invest this powerfull work environment. At all, many people (like myself) working on Un*x don't ever worked with batch files so your sample may be not as clear as you mind. In this present case, I did not understand your essential third paragraph about echo on and @. – F. Hauri Jan 2 at 12:21

3 Answers

up vote 5 down vote accepted

xtrace output goes to stderr, so you could redirect stderr to /dev/null:

ikwtd() {
  echo do stuff
} 2> /dev/null

If you still want to see the errors from the commands run inside the functions, you could do

ikwtd() (
  set +x
  exec 2>&3 3>&-
  echo do stuff
) 3>&2 2> /dev/null

See also this locvar.sh which contains a few functions to implement local scope for variables and functions in POSIX scripts and also provides with trace_fn and untrace_fn functions to make them xtraced or not.

share|improve this answer
Sweet! I was looking to see if there were any modifiers I could apply to the function itself, but I didn't think about simply redirecting stderr. Thanks! – clacke Jan 2 at 9:59
Btw, stchaz.free.fr/which_interpreter from the same page is pretty awesome and disturbing. :-) – clacke Jan 14 at 8:38
And now I came back here again for the second method, silencing set +x without silencing useful stderr output. Thanks again! – clacke Mar 4 at 12:00

The reason that set +x is printed is that set -x means "print the command you are about to run, with expansions, before running it. So the shell doesn't know that you want it to not print things until after it has printed the line telling it not to print things. To the best of my knowledge, there's no way of stopping that from happening.

share|improve this answer

First, you have to understand that, as you ask for

... old .bat days, when running with echo on, individual lines could be exempted by starting them with a @. Is there any equivalent in bash?

While I know Linux and bash well and because I don't know what's .bat concept, I can't rightly understand the meaning of your question.

At all, there is my answer in 3 points:

  1. As set -x is a debug solution, all commands have to be printer before execution in order to ensure they will be readable even if it make a big error.

  2. Parenthesis generate sub-shell where parameters like -x stay locally

  3. So you can make that in the both way: Set the flag in main script and remove them in some part, or else: remove the flag in mains script and set them in some parts.

At all, your sample work: line 6 is not printed.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.