14

I've seen that some people when writing bash script they define local variables inside an if else statement like example 1

Example 1:

#!/bin/bash

function ok() {
  local animal

  if [ ${A} ]; then
     animal="zebra"
  fi

echo "$animal"
}

A=true
ok

For another example, this is the same:

Example 2:

#!/bin/bash
function ok() {

  if [ ${A} ]; then
     local animal
     animal="zebra"
  fi

echo "$animal"
}

A=true
ok

So, the example above printed the same result but which one is the best practice to follow. I prefer the example 2 but I've seen a lot people declaring local variable inside a function like example 1. Would it be better to declare all local variables on top like below:

function ok() {
 # all local variable declaration must be here
 
 # Next statement
 
}
Kalib Zen
  • 655
  • 1
  • 5
  • 16

2 Answers2

24

the best practice to follow

Check your scripts with https://shellcheck.net .

Quote variable expansions. Don't $var, do "$var". https://mywiki.wooledge.org/Quotes https://www.shellcheck.net/wiki/SC2086

For script local variables, prefer to use lowercase variable names. For exported variables, use upper case and prefixed unique variable names.

Do not use function name(). Use name(). https://wiki.bash-hackers.org/scripting/obsolete (archive.org http://web.archive.org/web/20170123130003/http://wiki.bash-hackers.org/scripting/obsolete ).

Document the usage of global variables a=true. Or add local before using variables local a; then a=true. https://google.github.io/styleguide/shellguide.html#s4.2-function-comments

scope best practice

Generally, use the smallest scope possible. Keep stuff close to each other. Put local close to the variable usage. This is like the rule from C or C++, to define a variable close to its usage, but unlike in C or C++, in shell local declaration and assignment should be on separate lines, see https://www.shellcheck.net/wiki/SC2155 .

Note that your examples are not the same. In the case variable A (or a) is an empty string, the first version will print an empty line (the local animal variable is empty), the second version will print the value of the global variable animal (there was no local). Although the scope should be as smallest, animal is used outside of if - so local should also be outside.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • `global variable should be capital` No idea, It's a convention. I surely can find something. https://stackoverflow.com/questions/673055/correct-bash-and-shell-script-variable-capitalization not that far away. There reference would be from POSIX https://stackoverflow.com/a/52484424/9072753 . It comes from the fact, that people try to set `USER=me` reserved environment variables in scripts and then get suprising results. So it's best to avoid all upper case variables. https://pubs.opengroup.org/onlinepubs/007904875/basedefs/xbd_chap08.html . Use upper case for _exported_ variables, not "global" – KamilCuk Sep 20 '21 at 10:40
  • Normally I will capitalize all global variable and make the local variable as lowercase. What do you think ? U said about the USER, I actually never use this variable as I have a list that will not use reserved bash keyword or variable. – Kalib Zen Sep 20 '21 at 10:43
  • `What do you think ?` Use lowercase for all variables, use `g_*` prefix for global variables. Capitalize only _exported_ variables. `I have a list` Not all ppl have such list ;) – KamilCuk Sep 20 '21 at 10:44
  • Do you have any sources that said best practice to use lowercase for all variables? I know about the reserved keyword USER, PWD, OLDPWD.. I always avoid using them and subtitute with _. Example for `USER` I will use `MY_USER` – Kalib Zen Sep 20 '21 at 10:47
  • For example the stackoverflow question I linked: `Use "snake case" (all lowercase and underscores) for all variables that are scoped to a single script or a block.` also https://google.github.io/styleguide/shellguide.html#s7.2-variable-names . – KamilCuk Sep 20 '21 at 10:48
  • About the lowercase and uppercase, I never seen example that people would use lowercase for global variable (but i have seen a lot people use uppercase for global variable). Take this latest git code for example: https://github.com/mertcangokgoz/UsefulBashScripts/blob/master/Scripts/backup.sh. The link you gave to me did not explain whether the best practice to use lowercase for global variable or uppercase. – Kalib Zen Sep 20 '21 at 11:34
  • https://github.com/Bash-it/bash-it/blob/master/install.sh#L163 `The link you gave to me` which link? The gooogle shellguide? `Function Names Lower-case, with underscores to separate words` and `Variable Names As for function names.`. – KamilCuk Sep 20 '21 at 11:36
  • So, the bash-it link you provided, it has all global variables capitalized except the option list that they did not capitalize. For example the option `append_to_config` `overwrite_backup`. These are global variables. If you look at this `BACKUP_FILE=$CONFIG_FILE.bak`, it is capitalized. So I still don't get it when you should capitalize the global variable. If you look at the code, they did not follow what you just told me about using all variables to lowercase except the export one. – Kalib Zen Sep 20 '21 at 12:08
  • 1
    Your link on google.github.io talk about function names that should be lowercase, that is understandable but nowhere it said about using lowercase in global variable and the last line you were talking about empty string on variable. My only mistake in the code was not quoting the `${A}` test variable to avoid expansion and that was just example to run the code inside ifelse statement because my original question is about local variable scope inside ifelse statement. The only new thing I learn from you is not to use `function` to declare function. Thanks. – Kalib Zen Sep 20 '21 at 12:16
  • `when you should capitalize` It's a convention. You should prefer, it's a preference. If a variable acts like exported variable, is used in many functions, you could prefer to capitalize it. Like `BACKUP_FILE` - it is used in `_bash-it_check_for_backup`. Or the variable is some global read-only configuration- like `BASH_IT` the location of the framework. Overall, writing readable code is not about strictly following rules. – KamilCuk Sep 20 '21 at 12:20
  • OK, that is understandable. So, I can conclude that there is no best practice for variable capitalization only preference that people still don't prefer most of the time (this is proven in many bash codes in github). You made a mistake there the `BACKUP_FILE` is not used in `_bash-it_check_for_backup`.. It is just a standalone variable to declare the path of a backup file... and `BASH_IT` is not a readonly variable, you mean the export variable? Yes, it is used to export. – Kalib Zen Sep 20 '21 at 12:23
  • Kind of, yes. There are endless bad scripts on github, I wouldn't count it as an objective measure. Usually ppl write short scripts to do one short job, install stuff, edit stuff, who cares what variables it uses. But, still, the convention is: lowercase for function local, uppercase for exported, and there is the gray area for globals. – KamilCuk Sep 20 '21 at 12:25
  • Im going to give 50 bounties – Kalib Zen Sep 27 '21 at 14:59
1

The local command constrains the variables declared to the function scope.

With that said, you can deduce that doing so inside an if block will be the same as if you did outside of it, as long as it's inside of a function.

Dharman
  • 30,962
  • 25
  • 85
  • 135
javiervidrua
  • 69
  • 1
  • 4
  • But, what is the preferable way and more readable way... when you have a lot of local variable, shouldn't we just declare it on top like the java style? – Kalib Zen Sep 20 '21 at 10:40
  • It's up to you and your coding style. I prefer to declare variables at the top too :) – javiervidrua Sep 20 '21 at 20:55