Variable in Bash Script that keeps it value from the last time running
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"
bash—Better way to store variable between runs?
There's no need to use var
; x
will be in scope for the current shell. Alternately,
read var < var.txt
# do stuff with var
echo $var > var.txt
I recommend using a simple text file to store the variable. However, there is the (highly questionable) option of a self-modifying script. FOR ENTERTAINMENT PURPOSES ONLY!
#!/bin/bash
read val < <( tail -n 1 "$0" )
(( val++ ))
echo "$val"
tmp=$(mktemp /tmp/XXXXXXX)
sed '$s/.*/'$val'/' "$0" > "$tmp"
mv "$tmp" "$0"
exit
0
The key is to have the next-to-last line be the exit command, so nothing after it will execute. The last line is the variable value you want to persist. When the script runs, it read
s from its own last line. Before it exits, it uses sed
to write a copy of itself toa temp file, with the last line modified with the current value of the persistent value. Then we overwrite the current script with the temp file (assuming we will have permission to do so).
But seriously? Don't do this.
How to use Unix variables to set and retain values across session {bash}
Shell variables are stored per-process, since each shell script is its own process, you cannot persist variables across processes this way. There are various ways to communicate between processes, though:
- Pipes
- Shared Memory
- Message Queue
- Semaphores
- Files
For your purposes, it would seem that files are the easiest approach. Using bash, to write to the file:
echo $VAR > /tmp/process.tmp.file.txt
and read from it:
export VAR=`cat /tmp/process.tmp.file.txt`
remember bash variable for running script again
Launching the script from terminal makes the script inherit the environment variables from your terminal. Any environment variables set within that script are only valid during the execution time of the same script. As soon as it exits, away goes the environment variables.
You would have to use something else, files for instance, to keep track of changes during multiple executions of the script.
Bash: increment a variable from a script every time when I run that script
#!/bin/bash
n=0;#the variable that I want to be incremented
next_n=$[$n+1]
sed -i "/#the variable that I want to be incremented$/s/=.*#/=$next_n;#/" ${0}
echo $n
Variables getting reset after the while read loop that reads from a pipeline
I ran into this problem yesterday.
The trouble is that you're doing find $loc -name "*.bsp" | while read
. Because this involves a pipe, the while read
loop can't actually be running in the same bash process as the rest of your script; bash has to spawn off a subprocess so that it can connect the the stdout of find
to the stdin of the while
loop.
This is all very clever, but it means that any variables set in the loop can't be seen after the loop, which totally defeated the whole purpose of the while
loop I was writing.
You can either try to feed input to the loop without using a pipe, or get output from the loop without using variables. I ended up with a horrifying abomination involving both writing to a temporary file AND wrapping the whole loop in $(...)
, like so:
var="$(producer | while read line; do
...
echo "${something}"
done)"
Which got me var set to all the things that had been echoed from the loop. I probably messed up the syntax of that example; I don't have the code I wrote handy at the moment.
How do I set a variable to the output of a command in Bash?
In addition to backticks `command`
, command substitution can be done with $(command)
or "$(command)"
, which I find easier to read, and allows for nesting.
OUTPUT=$(ls -1)
echo "${OUTPUT}"
MULTILINE=$(ls \
-1)
echo "${MULTILINE}"
Quoting ("
) does matter to preserve multi-line variable values; it is optional on the right-hand side of an assignment, as word splitting is not performed, so OUTPUT=$(ls -1)
would work fine.
Bash - Using a static variable (aka Command line Russian Roulette)
Short answer: No, bash doesn't have "static" variables.
Longer: When your "C" program finishes its run, the "static" variable is lost. The same is applied for the bash script. So, you must decide what you want:
- run the script once, simulate the revolver (and you can use global variable to hold the revolver status)
- want preserve the revolver's cylinder status between each script run, so you need use some external storage to preserve the data. (for example file).
From you question i guessed the second version, so you must use file to hold the revolver status. For the game, you should divide the problem to different parts:
- roll - (roll the revolver's cylinder (random bullet position))
- shoot - (move the cylinder by one position and check the bullet)
I would do this as the following:
define the
revolver
for example as/tmp/revolver
.- It will have 6 lines, in each line could be 2 values:
0
- no bullet,1
- bullet - the hammer is in the 1st line - so, if the bullet is in the first line (e.g. the 1st line has value 1) the bullet will fire.
- each "roll" ensures than exactly ONE bullet is in the cylinder
- when shooting - once the bullet is fired, will not fire again, so any number of subsequent shots will not fire again
- It will have 6 lines, in each line could be 2 values:
the
roll
"command". Defined as an bash function and saved as./roll
command.
revolver="/tmp/revolver"
roll() {
cyl=(0 0 0 0 0 0) # empty cylinder
cyl[$(($RANDOM % 6))]=1 # one bullet at random position
printf "%d\n" "${cyl[@]}" >"$revolver" # save
}
roll #do the roll
now, you can do bash roll
(or after the chmod 755 roll
) simply ./roll
and your revolver is loaded with one bullet. Run the ./roll
few times and after each ./roll
check the bullet position with cat /tmp/revolver
.
- the
shoot
command should:- rotate the lines by one position (as in the real revolver)
- and cock the hammer - e.g. check the value of the 1st line
revolver="/tmp/revolver"
rollone() {
at_hammer=$1 # store what is under the hammer
shift # shift the rest by one position
printf "%d\n" "$@" 0 > "$revolver" # save new cylinder the status
# note, we adding to the last position 0,
# because when the bullet is fired it will not fire again
# out digital revolver is not jamming
echo $at_hammer # return the bullet yes/no
}
shoot() {
cyl=($(<"$revolver")) #load the revolver status
return $(rollone "${cyl[@]}") #make the shoot, roll the cylinder and return the status
}
boom() { echo "Boom"; } #the "boom" action
click() { echo "Click"; } #the "click" action
shoot && click || boom #the actual shot
Now you can play the game:
- a.
./roll
- load the revolver with one bullet and roll the cylinder - b.
./shoot
- any number of times
The whole game as script.
Variant A - roll once and shooting multiple times i
./roll
while :
do
./shoot
done
this will output something like:
Click
Click
Boom
Click
Click
... and forever ...
Click
Variant B - roll (e.g. reload with 1 bullet) between each shot
while :
do
./roll
./shoot
done
this will prints e.g.:
Click
Click
Boom
Boom
Click
Click
Click
Boom
Click
Click
Click
Click
Click
Click
Click
Click
Click
Boom
Click
... etc ...
Also, you could extend/modify the scripts with one more command: load
and redefine your revolver as:
load
- will load one (or more) bullet(s) into the cylinderroll
- will rotate the cylinder by the random number of positions (but NOT reloads the bullet) - e.g. after the fired bullet the roll will rotate only empty cylindershoot
- fire the gun (no modification needed).
Related Topics
How to Execute Ssh-Keygen Without Prompt
What Do the Numbers in /Proc/Loadavg Mean on Linux
Linux: Command to Open Url in Default Browser
How to Upgrade Aws Cli to the Latest Version
How to Split a File and Keep the First Line in Each of the Pieces
Bash: Inserting a Line in a File at a Specific Location
Uevent Sent from Kernel to User Space (Udev)
Linux: Find All Symlinks of a Given 'Original' File? (Reverse 'Readlink')
Why Doesn't Linux Use the Hardware Context Switch via the Tss
Reading Living Process Memory Without Interrupting It
What's the Purpose of Each of the Different Uids a Process Can Have
What Is the Purpose of Map_Anonymous Flag in Mmap System Call
How to Parse CSV Files on the Linux Command Line
How to Sort a File, Based on Its Numerical Values for a Field
Unix Standard Directory to Put Custom Executables or Scripts
Difference Between Arm-Eabi Arm-Gnueabi and Gnueabi-Hf Compilers