Surprising Bash Variables
Interesting list (not very surprising to me personally though saw $REPLY mentioned anywhere after a long time). One that surprised me recently (in a how-come-I-didn't-know-about-it-for-so-long way) was $PIPESTATUS e.g. if you are running a pipeline "cmd1 | cmd 2" and would like to know the return status of cmd1, you can use ${PIPESTATUS[0]} to get that. Useful, e.g. when you are tee-ing the output etc.
WARNING: this page has a dangerous typo. do not put '.' in your path.
"This is similar to the confusion I felt when I realised the dot folder was not included in my more familiar PATH variable… but you should [not] do that in the PATH variable because you can get tricked into running a ‘fake’ command from some downloaded code."
If you set $CDPATH, then for goodness’ sake don’t export it. It changes the behaviour of the cd command to make it output the absolute path of the directory changed to, which breaks a common shell-scripting pattern for converting relative directory paths to absolute paths, viz:
Conversely, if you’re writing a bash script and it needs to be robust against people who do export CDPATH, you can do it like this instead:absolute=$(cd "$relative" && pwd)
absolute=$(CDPATH=. cd "$relative")
As much as people use the shell, it’s regrettable how few have actually read the manual. Anything you use for extended periods of time on a regular basis is worth sitting down and reading the manual for.
This is similar to the problems seen when the dot folder is not included in the more familiar PATH variable
FWIW I don't think I've ever seen this done in any system anywhere. My usual expectation is that local executables are run as "./foo".
My problem with bash is that things are not very discoverable. There is so much cool stuff you find out even after ten years of using it daily. I wonder if there is a way to have all its features in a less obscure language.
"There are dark corners in the Bourne shell, and people use all of them."
https://books.google.com/books?id=KJQRAwAAQBAJ&pg=PA36&lpg=P...
>4) SHLVL: [...] This can be very useful in scripts where you’re not sure whether you should exit or not, or keeping track of where you are in a nest of scripts.
If you're writing recursive shell scripts where you're not sure whether you should exit or not, you shouldn't be writing shell scripts.
Leave it to bash to go out of its way to make it easier to write scripts that break encapsulation and implement spooky mysterious action-at-a-distance by implicitly depending on how they were run, and purposefully behave differently whether they're invoked from a command line or another script, and are so confused about what they should do that they have to make guesses about whether or not to exit.
@zwischenzug in case you’re not aware, visiting your site on mobile sometimes forwards on to a spammy third party ad site.
> This is similar to the problems seen when the dot folder is not included in the more familiar PATH variable.
Is this implying that you should put `.` on PATH? I've always heard that to be a security problem.
What's interesting is that so many of these variables are incredibly tersely named. What's the reasoning behind not using a full name for them to make Bash actually readable? Surely not the minor performance scrape?
A lot of those variables come straight from Korn shell and are well documented in the Bolsky and Korn book.
One very useful one not mentioned on this page, possibly because considered well-known: $RANDOM
undefined
There is also BASH_REMATCH[0] used in conjunction with the regex comparison "=~" to capture subpatern
Here is a function to convert HH:MM:SS to seconds:
[0]: https://www.gnu.org/software/bash/manual/html_node/Bash-Vari...toseconds() { # https://stackoverflow.com/a/12986612/1469043 Time="$1" while :; do if [[ $Time =~ ^([0-9]{2}):([0-9]{2}):([0-9]{2})$ ]]; then if [[ ! BASH_REMATCH[3] < 60 ]]\ && [[ ! BASH_REMATCH[2] < 60 ]]\ && [[ ! BASH_REMATCH[1] < 24 ]]; then break fi fi read -p "Wrong format. Please use the HH:MM:SS format: " -e Time done echo "$Time" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }' }
PROMPT_COMMAND ( is one of the powerful ones. I have modified my own to log the commands into timestamped based log files.
I have to say that the LINENO variable does not have the expected behavior in process substitutions, especially when using multi-line commands (with backslashes at the end, or using multi-line strings).
LINENO will use the last line number of a multi-line "$(...)" command, offsetting all the commands' line numbers within the substitution. Since multi-line strings are concatenated by Bash internally, LINENO will only increase by one for those.
You end up with line numbers greater than the number of lines in your file, or overlapping with empty lines or comments. In this matter, Zsh's LINENO is way better as it will have the expected value (it will always be the line where the command was started, not an offset).
Bash seems like a language written by people who never intend to do the same thing twice.
I find it surprising that the fellow that coined the word POSIX, agreed to censoring the POSIX_ME_HARDER variable.
It's also surprising that the first version of bash committed source code suicide via a bug in globbing, which makes it's name seem more poignant, and was why there was a file named "-i" in it's source tree for many years.
HISTTIMEFORMAT is something I’ve wanted for so long but never knew existed. I should probably read man pages more!
Overall, I feel like "Surprising" is the word that best describes "Bash".
Cool list, couple or three were new to me. Thanks for posting!
Surprised to see that $RANDOM was not there. Who would have known!
ssuhhhhhhh
suhhhhhhh