18

Can I create a Bash script with persistent variable-values?

For example, I initialize a variable with 0 when the script runs for the first time (during a specific time limit), and the variable increases automatically with every time the script is running.

1

3 Answers 3

24

You can't, but you can use a file to do it

#!/bin/bash

valuefile="/tmp/value.dat"

# if we don't have a file, start at zero
if [ ! -f "$valuefile" ]; then
    value=0

# otherwise read the value from the file
else
    value=$(cat "$valuefile")
fi

# increment the value
value=$((value + 1))

# show it to the user
echo "value: ${value}"

# and save it for next time
echo "${value}" > "$valuefile"
Sign up to request clarification or add additional context in comments.

7 Comments

Note that expr is an artifact from the 1970s. All shells compliant with the POSIX sh standard support value=$((value + 1)), whereas expr is not part of the standard and not guaranteed to be present in new, POSIX-compliant shells and operating systems.
@CharlesDuffy which operating system doesn't have expr (or at least busybox)? please summate 15904148959 + 1 and see why we should prefer expr before aritmethic expansion
@alecxs, you're moving the goalpoasts -- with built-in POSIX shell math, it's a shell feature and you don't need your operating system to provide any binaries external to the shell. You don't spend the time loading the external binary to execute that feature; you don't need an extra fork() for a command substitution to capture its output; you don't need to worry about whether implementations vary (and they do vary; I've seen some supporting regex features, for example, whereas others don't). And how expr handles overflow is OS-by-OS dependent...
On any 64-bit platform where the shell is bash, I recommend value=$((value + 1)), which will correctly handle any partition size in bytes that your OS can handle (contrary to your prior assertion, echo $((15904148959 + 1)) works fine). If you're on a 32-bit system that can't handle that, then value=$(bc <<<"$value + 1")
Talk to the people who decided to compile that specific copy of busybox to provide expr (which isn't standard-mandated or even referenced), but not bc (which is both). Note that busybox is fully configurable -- it can provide bc, and it can fail to provide expr. But the one that fails to provide expr is still standards-compliant; the one that fails to provide bc isn't.
|
3

I'm afraid you have to save the state in a file somewhere. The trick is to put it somewhere the user will be able to write to.

yourscriptvar=0

if [ -e "$HOME/.yourscriptvar" ] ; then
    yourscriptvar=$(cat "$HOME/.yourscriptvar")
fi

# do something in your script

#save it output the file
echo $yourscriptvar > "$HOME/.yourscriptvar"

1 Comment

Here's a bash-ism: yourscriptvar=$(< "$HOME/.yourscriptvar"). Documented here
3

I had the same problem a few days ago and I've written my own tool to do the work because there is not other way to do something similar.

gvar is a pure Bash key-value store where each user has a different collection of data. The records are stored in the user's home directory.

Here it is the most interesting functions from the source code:

get_variable() {
  cat $FILE | grep -w $1 | cut -d'=' -f2
}

set_variable() {
  echo $1=$2 >> $FILE
}

remove_variable() {
  sed -i.bak "/^$1=/d" $FILE
}

2 Comments

Huh. You would think that for such a 'library' it would be optimized for speed. For example, cat is unnecessary if you use grep since grep can already take a file as an argument. Besides, I wonder how this would work well in parallel execution if it doesn't use flock or something.
@Yeti you are completely right, gvar is just a toy that resolved my problem but I haven't gone forward. I thought similar things that you pointed out. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.