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?

2
  • 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, 2021 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, 2021 at 15:38

2 Answers 2

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.

3
  • 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). Jun 10, 2021 at 17:18
  • This is great, thankyou. The shellcheck thing is particularly useful. Jun 13, 2021 at 2:35
  • You're welcome. If you found the answer useful, please consider accepting is to that others facing a similar issue may find it more easily.
    – AdminBee
    Jun 14, 2021 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.

0

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.