1

I'm writing my first bash script to automate a back up. I'm stuck almost on the first hurdle.

I want use variables to make a file name for a tar archive. I want a filename that looks like hostname date time.tar.bz2. I can get that on its own using $(hostname)_$(date +"%FT%T"), but I can't seem to work it into a variable.

My "test script" looks like this:

#! /bin/bash


NAME=$($(hostname)_$(date +"%FT%T"))

tar -cjvf "$(NAME).tar.bz2" testing testing2

(where testing and testing2 are dummy directories for, well, testing.)

Unfortunately, it does this:

$ scripts/trial.sh
scripts/trial.sh: line 6: NAME: command not found

Thu Jun 10 23:11:06 AEST 2021

I've tried to breakdown the declaration of NAME as a work around

#! /bin/bash

## test of bits and pieces

NAME=$(hostname)_$(date +"%FT%T")
NAME_VAR=$(NAME)

Test=$(date)

echo $NAME_VAR
echo $Test

tar -cjvf "$(NAME_VAR).tar.bz2" testing testing2

Which gets the following in terminal:

$ scripts/trial.sh
scripts/trial.sh: line 6: NAME: command not found

Thu Jun 10 23:34:37 AEST 2021
scripts/trial.sh: line 13: NAME_VAR: command not found
testing/
testing2/

I just cannot see why this should be happening. What am I missing?

AdminBee
  • 21,637
  • 21
  • 47
  • 71
  • At least GNU tar doesn't like your date format with colons (see option `-f`). It expects a remote hostname/IP before the colon and a path after the colon. – Freddy Jun 10 '21 at 14:22
  • 1
    "_I'm writing my first bash script to automate a back up. I'm stuck almost on the first hurdle._" you might want to consider using an existing solution. Backups are important enough that creating them from your first scripting attempt is a good challenge but perhaps not well advised – roaima Jun 10 '21 at 15:38

2 Answers2

1

If these are your first attemts at shell scripting, I would recommend using shellcheck to "proof-read" shell scripts; it is also available as standalone program on many Linux distributions.

For the problems you are facing: You seem to be mixing up the shell and Makefile syntax for dereferencing variables. In shell, $NAME is the value of the variable NAME, whereas $(NAME) would try to execute a command NAME and return the output of that command - a so-called "command substitution" (which you correctly used in filling NAME in your "test of bits and pieces" workaround).

So, the corrected script would look like

NAME="$(hostname)_$(date +"%FT%T")"
tar -cjvf "$NAME.tar.bz2" testing testing2

As a side-note

  • all-uppercase variable names should not be used unless you export them as environment variables to the shell, since they might otherwise clash and overwrite essential environment variables, such as $PATH.
  • be sure to correctly quote your variable references, in particular when a variable contains a file name. Otherwise, your shell script may stumble on file names with special characters like spaces, *, ?, newlines (yes, even these are allowed in file names!) and the like.

I would recommend you to have a look at

for further reading.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
AdminBee
  • 21,637
  • 21
  • 47
  • 71
  • 2
    See also `uname -n` as a standard equivalent of `hostname`. The `bash` shell also sets the `$HOSTNAME` variable. (`printf -v file "%s_%(%FT%T)T.tar.bz2" "$HOSTNAME" -1` as a builtin way to do it). – Stéphane Chazelas Jun 10 '21 at 17:18
  • This is great, thankyou. The shellcheck thing is particularly useful. – account-minute Jun 13 '21 at 02:35
  • You're welcome. If you found the answer useful, please consider [accepting](https://unix.stackexchange.com/help/accepted-answer) is to that others facing a similar issue may find it more easily. – AdminBee Jun 14 '21 at 13:02
0

The first line should be:

NAME=$(hostname)_$(date +"%FT%T")

With the way that you have it, it's going to use command substitution and treat the output as a command and because it doesn't exist, you'll get the error.

The last line could just be this:

tar -cjvf "$NAME.tar.bz2" testing testing2

For future reference, you can use shellcheck.net to verify your scripts.

roaima
  • 107,089
  • 14
  • 139
  • 261
Nasir Riley
  • 10,665
  • 2
  • 18
  • 27