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
  • 22,803
  • 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 – Chris Davies 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.

AdminBee
  • 22,803
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.

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
Nasir Riley
  • 11,422