Suppress the bash execution trace (set -x) from the outside of the script
With bash
4.1 and above, you can do
BASH_XTRACEFD=7 ./script.bash 7> /dev/null
(also works when bash
is invoked as sh
).
Basically, we're telling bash
to output the xtrace
output on file descriptor 7 instead of the default of 2, and redirect that file descriptor to /dev/null
. The fd number is arbitrary. Use a fd above 2 that is not otherwise used in your script. If the shell you're entering this command in is bash
or yash
, you can even use a number above 9 (though you may run into problems if the file descriptor is used internally by the shell).
If the shell you're calling that bash
script from is zsh
, you can also do:
(export BASH_XTRACEFD; ./script.bash {BASH_XTRACEFD}> /dev/null)
for the variable to be automatically assigned the first free fd above 9.
For older versions of bash
, another option, if the xtrace
is turned on with set -x
(as opposed to #! /bin/bash -x
or set -o xtrace
) would be to redefine set
as an exported function that does nothing when passed -x
(though that would break the script if it (or any other bash
script it invokes) used set
to set the positional parameters).
Like:
set()
case $1 in
(-x) return 0;;
(-[!-]|"") builtin set "$@";;
(*) echo >&2 That was a bad idea, try something else; builtin set "$@";;
esac
export -f set
./script.bash
Another option is to add a DEBUG trap in a $BASH_ENV
file that does set +x
before every command.
echo 'trap "{ set +x; } 2>/dev/null" DEBUG' > ~/.no-xtrace
BASH_ENV=~/.no-xtrace ./script.bash
That won't work when set -x
is done in a sub-shell though.
As @ilkkachu said, provided you have write permission to any folder on the filesystem, you should at least be able to make a copy of the script and edit it.
If there's nowhere you can write a copy of the script, or if it's not convenient to make and edit a new copy every time there's an update to the original script, you may still be able to do:
bash <(sed 's/set -x/set +x/g' ./script.bash)
That (and the copy approach) may not work properly if the script does anything fancy with $0
or special variables like $BASH_SOURCE
(such as looking for files that are relative to the location of the script itself), so you may need to do some more editing like replace $0
with the path of the script...
Since they're scripts, you could make copies of them, and edit those.
Other than that, filtering the output would seem simple, you could explicitly set PS4
to something more unusual than a single plus, to make the filtering easier:
PS4="%%%%" bash script.sh 2>&1 | grep -ve '^%%%%'
(of course that will collapse stdout and stdin, but piping just stderr in Bash gets a bit hairy, so I'll ignore that)