I wrote this bash script, but it doesn't work.

dex=`date +%Y%m%d`

if [ -f "bv$dex.txt" ]; 

eval bv$dex=`cat ./bv$dex.txt`
let bv$dex+=1 ;
echo $bv$dex > ./bv$dex.txt

echo 1 > ./bv$dex.txt


For some reason it just writes variable dex in file, instead of number + 1

  • This is the expected behavior since there is no variable named bv$dex, but can you explain a bit more what you are trying to do? It is possible to use indirect expansion for variable names, but it is quite complicated and absolutely unnecessary for the script you show: you can just use a different variable name. So, is this a simplified example of what you are really trying to do and, if so, what is it you are trying to do so we can see if we can find an alternative?
    – terdon
    Dec 28, 2021 at 16:12
  • Also, in almost all cases where people think that indirect expansion is the answer, they should be using an array instead.
    – cas
    Dec 28, 2021 at 22:47

2 Answers 2


As others have said, you could avoid this by using a simpler variable name for the file name, like counter=$(cat "bv$(date +%Y%m%d)").

But if you would like to understand why it doesn't work, the problem is this line:

echo $bv$dex > ./bv$dex.txt

The command echo $bv$dex is evaluating $bv and $dex as two separate expressions, and concatenating the results. Note $bv is undefined, therefore it evaluates to "" (empty string) *. So this is equivalent to echo $dex which just prints the date.

Instead, you would want

eval echo \$bv$dex > ./bv$dex.txt

If dex=20211228 (for example), then the expression \$bv$dex evaluates to the literal string $bv20211228, since the \$ is treated as a literal $ and not a variable reference. So this eval command then becomes echo $bv20211228, which yields the result you expect.

Just because this is possible though, doesn't mean it is a good idea :)

* If you add set -u to the top of your script, it will fail while evaluating, instead of evaluating to an empty string. I highly recommend adding set -eu as the first line of your scripts, right after the shebang #!/bin/bash.


From the code given, the filename appears to be invariant once the date is known.

There is no merit in having the variable name match the file's basename.

#.. Create the full filename.
printf -v Fn 'bv%(%Y%m%d)T.txt' -1

#.. Create or fetch the serial number.
[[ -r "${Fn}" ]] && read -r Num < "${Fn}"

#.. Write the incremented serial.
printf > "${Fn}" '%d\n' $(( ++Num ))

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.