diff --git a/SC2262.md b/SC2262.md new file mode 100644 index 0000000..375067f --- /dev/null +++ b/SC2262.md @@ -0,0 +1,72 @@ +## This alias can't be defined and used in the same parsing unit. Use a function instead. + +### Problematic code: + +```sh +function checksum() { + type md5 && alias md5sum=md5 + md5sum "$@" # This calls `md5sum`, not `md5` +} +``` + +### Correct code: + +```sh +function checksum() { + type md5 && md5sum() { md5sum "$@"; } + md5sum "$@" # Now this would call `md5` when applicable +} +``` +### Rationale: + +Alias expansion happens at parse time, which means to have an effect, the `alias` command must be executed not just before the alias is invoked, but before the invocation is parsed. + +A shell will parse commands until it has a complete set of commands followed by a linefeed. This includes compound commands like `{ brace; groups; }` and `while loops; do true; done`. Here are some examples: + + # A single command followed by a linefeed is one unit + unit 1 + + # These commands are in the same parsing unit because + # there is no line feed between them + unit 2; unit 2; + + # These commands are in the same parsing unit because + # they are part of the same top level brace group + { + unit 3 + unit 3 + } + + # These commands are in the same parsing unit because + # there is no linefeed between the groups. + { + unit 4 + }; { + unit 4 + } + +Any alias defined in a command in `unit 1` would not take effect until `unit 2` and beyond. Similarly, an alias defined in unit 2 will only take effect in unit 3 and 4. + +In the problematic example, the alias is defined and used in a function. Since a function definition is a single compound command, it's considered a single parsing unit. The alias would therefore not have an effect (this is true even if the function is invoked twice, because it's only parsed once). + +Does this sound confusing and counter-intuitive? It is. Save yourself the trouble and always use functions instead of aliases. + +### Exceptions: + +If the flagged commands are not expected to use the alias, you can ignore this error. ShellCheck may incorrectly flag this if the alias definition and usage were in different branches of an `if` statement. + +You can [[ignore]] this warning with a directive. All warnings may always be disabled either before the relevant command or before any outer compound commands, but in this case it's especially useful: + + # shellcheck disable=SC2262 # Option A, before compound command + if true + then + # shellcheck disable=SC2262 # Option B, before alias command + alias foo=bar + # With either Option A or B, this SC2263 message is auto-suppressed + foo + fi + +### Related resources: + +* Unix&Linux SE: [bash aliases do not expand even with shopt expand_aliases](https://unix.stackexchange.com/questions/502257/bash-aliases-do-not-expand-even-with-shopt-expand-aliases) +* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc! \ No newline at end of file