258

I have the following script I wrote by searching Google, and it backs up my Linux system to an archive:

#!/bin/bash
# init

DATE=$(date +20%y%m%d)

tar -cvpzf /share/Recovery/Snapshots/$HOSTNAME_$DATE.tar.gz --exclude=/proc --exclude=/lost+found --exclude=/sys --exclude=/mnt --exclude=/media --exclude=/dev --exclude=/share/Archive /

This works, but I am wondering if I can format the script to show the command over multiple lines, something like this, so it is easy to edit later:

tar -cvpzf /share/Recovery/Snapshots/$HOSTNAME_$DATE.tar.gz 
--exclude=/proc 
--exclude=/lost+found 
--exclude=/sys 
--exclude=/mnt 
--exclude=/media 
--exclude=/dev 
--exclude=/share/Archive 
/

That way it is easier to read and edit later. Is it possible to format a Bash script this way?

5 Answers 5

341

All you should need to do is add a \(backslash) at the end of each line and it should be good to go.

So yours will look like:

tar -cvpzf /share/Recovery/Snapshots/$(hostname)_$(date +%Y%m%d).tar.gz \
    --exclude=/proc \
    --exclude=/lost+found \
    --exclude=/sys \
    --exclude=/mnt \
    --exclude=/media \ 
    --exclude=/dev \
    --exclude=/share/Archive \
    /

A Few Shortcuts

(based on your comment update for setting $HOSTNAME)

$HOSTNAME

Two options to set that:

  1. Set HOSTNAME

HOSTNAME=$(hostname)

  1. Use command substitution (e.g. $(command))

So it would look like above. That just makes the command run before using it.

$DATE

Another variable avoided would be easily:

$(hostname)_$(date +%Y%m%d).tar.gz \

$ man date will have the formats for the date options, the above is YYYYmmdd

7
  • Thanks guys. One last thing. There seems to be a problem with the file name portion of my script: $HOSTNAME_$DATE.tar.gz When I run the script now, the output file is: 20121120.tar.gz Commented Nov 21, 2012 at 3:26
  • If you want your actual "hostname" put it in back ticks (the tilde "~" key above tab): /share/Recovery/Snapshots/`hostname`_$DATE.tar.gz
    – nerdwaller
    Commented Nov 21, 2012 at 3:36
  • Anytime @JayLaCroix - Welcome to SU!
    – nerdwaller
    Commented Nov 21, 2012 at 3:40
  • 2
    It is recommended to use $(command) instead of `command`.
    – andrybak
    Commented Jan 25, 2015 at 10:46
  • This works with withspaces as a separator. If I have ssh on the first line and commands on the following lines, I think I need a semicolon as well besides backslash.
    – Timo
    Commented Nov 22, 2020 at 8:23
26

Use the backslash to continue a command on the next line:

tar -cvpzf /share/Recovery/Snapshots/$HOSTNAME_$DATE.tar.gz \
--exclude=/proc \
--exclude=/lost+found \
--exclude=/sys  \
--exclude=/mnt  \
--exclude=/media  \
--exclude=/dev \
--exclude=/share/Archive \
/
5
  • I went back to update it to make it more useful and get the indentations. I love SU though, by and large.
    – nerdwaller
    Commented Nov 21, 2012 at 3:35
  • This doesn't work for me like eg. in alias ub='source ~/.bash_aliases \ && source $HOME/.bash_aliases \ && echo "aliases updated."'; Commented Oct 5, 2016 at 17:12
  • 1
    @TheDefinitionist Sounds like a different problem to this one. Perhaps open a new question?
    – Paul
    Commented Oct 6, 2016 at 2:58
  • 1
    Can I line up the backslashes in a column on the right?
    – SDsolar
    Commented Jul 30, 2017 at 23:45
  • @SDsolar You can use spaces and tabs to line up the slashes.
    – Paul
    Commented Jul 31, 2017 at 0:53
23

You can use this in bash

PARAMS=(
    -cvpzf /share/Recovery/Snapshots/$HOSTNAME_$DATE.tar.gz 
    --exclude=`enter code here`/proc 
    --exclude=/lost+found 
    --exclude=/sys 
    --exclude=/mnt
    # this is a comment 
    --exclude=/media 
    --exclude=/dev 
    # --exclude=/something
    --exclude=/share/Archive 
    /
)
# the quotes are needed to preserve params with spaces
tar "${PARAMS[@]}"
2
  • 3
    Should be tar "${PARAMS[@]}", so that params with spaces get preserved.
    – timkay
    Commented Mar 19, 2022 at 17:25
  • Note that these are just PARAMS for the previous app, if you want to chain it with another action, such as redirecting stout and stderr to a file, that still has to go after. For example, tar "${PARAMS[@]}" &> my-logs.log Commented Apr 29, 2023 at 20:04
13

The same command, but with comments for each line, would be:

tar -cvpzf /share/Recovery/Snapshots/$(hostname)_$(date +%Y%m%d).tar.gz `#first comment` \
    --exclude=/proc `#second comment` \
    --exclude=/lost+found `# and so on...` \
    --exclude=/sys \
    --exclude=/mnt \
    --exclude=/media \ 
    --exclude=/dev \
    --exclude=/share/Archive \
    /
1
  • This technique is not recommended when performances matter: "note that this technique is expensive because it creates a subshell for each of such “inline comments” during execution. It is only suitable if the commands performance or cost is not a problem." Source: systutorials.com/…
    – roneo.org
    Commented Apr 10, 2022 at 4:54
4

Axel Heider provided a good alternative to backslashes. Two notes:

  1. The command can be included in the list, and
  2. The use of the list should be in double quotes "${PARAMS[@]}", so that any spaces in parameters get preserved.
#!/bin/bash

params=(
    show
    hello,
    world
    "multi word"
)

function show {
    echo --- Showing \""$@"\" as parameters ---
    for i in "$@"; do
        echo i=$i
    done
}

${params[@]}
"${params[@]}"

outputs

$ bash test.sh
--- Showing "hello, world multi word" as parameters ---
i=hello,
i=world
i=multi
i=word
--- Showing "hello, world multi word" as parameters ---
i=hello,
i=world
i=multi word

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .