Technic1an Technic1an - 3 months ago 10x
Bash Question

How to increment a global variable within another bash script


I want to have a bash script that will have a global variable that can be incremented from other bash scripts.

I have a script like the following:

#! /bin/bash
export Counter=0
for SCRIPT in /Users/<user>/Desktop/*sh
echo $Counter

That script will call all the other bash scripts in a folder and those scripts will have something like the following:

if [ "$Output" = "$Check" ]
echo "OK"

I want it to then increment the $Counter variable if it does equal "OK" and then pass that value back to the initial batch script so I can keep that counter number and have a total at the end.

Any idea on how to go about doing that?


Environment variables propagate in one direction only -- from parent to child. Thus, a child process cannot change the value of an environment variable set in their parent.

What you can do is use the filesystem:

export counter_file=$(mktemp "$HOME/.counter.XXXXXX")
for script in ~user/Desktop/*sh; do "$script"; done

...and, in the individual script:

counter_curr=$(< "$counter_file" )
(( ++counter_curr ))
printf '%s\n' "$counter_curr" >"$counter_file"

This isn't currently concurrency-safe, but your parent script as currently written will never call more than one child at a time.

An even easier approach, assuming that the value you're tracking remains relatively small, is to use the file's size as a proxy for the counter's value. To do this, incrementing the counter is as simple as this:

printf '\n' >>"$counter_file"

...and checking its value in O(1) time -- without needing to open the file and read its content -- is as simple as checking the file's size; with GNU stat:

counter=$(stat --format=%z "$counter_file")

Note that locking may be required for this to be concurrency-safe if using a filesystem such as NFS which does not correctly implement O_APPEND; see Norman Gray's answer (to which this owes inspiration) for a working implementation.