211

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

278

All you should need to do is add "\" 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)

  2. 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

6
  • 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 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
    Nov 21, 2012 at 3:36
  • Anytime @JayLaCroix - Welcome to SU!
    – nerdwaller
    Nov 21, 2012 at 3:40
  • 2
    It is recommended to use $(command) instead of `command`.
    – andrybak
    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
    Nov 22, 2020 at 8:23
23

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
    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."'; Oct 5, 2016 at 17:12
  • 1
    @TheDefinitionist Sounds like a different problem to this one. Perhaps open a new question?
    – Paul
    Oct 6, 2016 at 2:58
  • Can I line up the backslashes in a column on the right?
    – SDsolar
    Jul 30, 2017 at 23:45
  • @SDsolar You can use spaces and tabs to line up the slashes.
    – Paul
    Jul 31, 2017 at 0:53
16

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[@]}"
1
  • 3
    Should be tar "${PARAMS[@]}", so that params with spaces get preserved.
    – timkay
    Mar 19 at 17:25
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
    Apr 10 at 4:54
3

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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