10

Sometimes it is really handy to just add

set -x

to the top of your script to show all commands before they are executed.

There is only one drawback creating scripts with a decent output: I don't know how to add text output to the script this way. If I use

echo 'some comment'

it will result in printing it doubled:

+ echo 'some comment'
some comment

And if I use # it isn't shown at all.

How can I add comments that are printed out like with echo? If I use set -x?

rubo77
  • 28,966

4 Answers4

13

One hacky way is just to write your comments as arguments to a no-op command. Particularly useful might be the : null utility:

set -x
: Some interesting notes on the following are ...

results in:

+ : Some interesting notes on the following are...

The colon command does nothing, accepts whatever arguments you give it, and always succeeds. You get an extra : at the start of your trace output, but that probably isn't a huge problem for your purpose.

If you don't like the : an even nastier trick is to use a fake command:

set -x
seq 1 1
Some comment &>/dev/null
true

will output:

+ seq 1 1
1
+ Some comment
+ true

That is, the Some comment line is printed out as trace output when the shell tries to run it, but the resulting error message is sent to /dev/null. This is nasty for a lot of obvious reasons, but it also counts as an error for the purposes of set -e.


Note that in either case, your comment is parsed by the shell in the ordinary way, so in particular if you have any special characters they need to be quoted, and because it's trace output the quoting will be displayed.

Michael Homer
  • 76,565
  • Maybe you could create a null function ___ () somehow? to use instead of the : somehow? this would look nicer: ___ some comment – rubo77 Jul 09 '14 at 12:39
  • @rubo77, sure - if you don't mind the extra obfuscation, you could do ___(): to define a function named ___ that does nothing. – godlygeek Jul 09 '14 at 13:47
  • I would use the colon (:) command which is reserved for do-nothing. I don't like the second method about typing an English sentence instead of a command. Technically, you can make a command "Some". – Culip Jul 20 '20 at 21:16
5

Instead of using "set -x" to print out the debug information, use a separate debug function:

#!/bin/bash

DEBUG=1

debug() {
    if [ $DEBUG == 1 ]
    then
    echo "DEBUG:" $@
    fi
}

debug "foo bar"

Running the script yields

temeraire:ul jenny$ ./testdebug.sh 
DEBUG: foo bar

If you change the assignment to instead read DEBUG=0, it won't print out the line.

Jenny D
  • 13,172
3

I use set -x to debug scripts all the time, and have only ever found the solution that @MichaelHomer suggests which makes use of the null utility (aka. : ..some comment...).

When you're ready to move to a more potent solution I'd suggest implementing your scripts using and actual logger such as log4Bash.

Example

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

Results:

   ss #1

slm
  • 369,824
-1

You can use the null command : which does nothing:

: ::::::: your comment here

Note: be sure not to use bash special characters in your comment like (, $, !, [, ... otherwise those will still be interpreted

To make it even more readeable, you could change the + to a string of your desire by setting PS4, e.g.:

PS4=": "; set -x
rubo77
  • 28,966