16

I'm using a Mac and I have this alias defined in .bashrc:

$cat .bashrc | grep la
alias la='ls -la'

then I try to use it in a script:

$cat ./mytest.sh  
#!/bin/bash
la

It runs and says it cannot find la:

./mytest.sh: line 2: la: command not found

Why is this? I tried on both Mac and Linux, same error!

codeforester
  • 39,467
  • 16
  • 112
  • 140
Hind Forsum
  • 9,717
  • 13
  • 63
  • 119
  • 2
    @anubhava: "Subshell" is a term of art that doesn't seem to apply here. I guess you mean something like "invoked shell scripts", but in that case you're simply describing the behavior the OP observed, rather than explaining it. – ruakh Jun 06 '17 at 06:34
  • Using aliases inside a script is not a good practice. Use functions instead. Also, making scripts dependent on `.bashrc` is not ideal as well. See this post: https://unix.stackexchange.com/questions/1496/why-doesnt-my-bash-script-recognize-aliases – codeforester Jun 06 '17 at 17:01

3 Answers3

21

Your .bashrc is only used by interactive shells. https://www.gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files says:

Invoked non-interactively

When Bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

but the value of the PATH variable is not used to search for the filename.

As noted above, if a non-interactive shell is invoked with the --login option, Bash attempts to read and execute commands from the login shell startup files.

As you can see, there's nothing about .bashrc there. Your alias simply doesn't exist in the script.


But even if .bashrc were read, there's another problem:

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt.

So if you wanted aliases to work in a script, you'd have to do shopt -s expand_aliases first. Or just use a shell function instead of an alias:

la() {
    ls -la
}
Community
  • 1
  • 1
melpomene
  • 84,125
  • 8
  • 85
  • 148
  • 3
    After the `shopt -s expand_aliases` line, my script also had to include `source ~/.bash_profile` for my file containing alias definitions. – wrapperapps Dec 28 '18 at 12:20
12

The simplest answer is to fix this issue is to do the 2 important things in your script -or it wont' work, if you just do one thing.

#!/bin/bash -i

# Expand aliases defined in the shell ~/.bashrc
shopt -s expand_aliases

After this, your aliases that you have defined in ~/.bashrc they will be available in your shell script (giga.sh or any.sh) and to any function or child shell within such script.

If you don't do that, you'll get an error:

your_cool_alias: command not found
AKS
  • 16,482
  • 43
  • 166
  • 258
  • 1
    Hi! The `shopt -s expand_aliases` line seems like no effect _for me_. It was actually enough the `#!/bin/bash -i` line without the `shopt -s expand_aliases` line when I executed the script with `./script.sh` inside the graphical terminal (kde Konsole). Similarly, it was running script with `bash -i script.sh` , i.e. interactively (with -i) instead of `bash script.sh` that worked without both the two lines. Although I did not find a way to execute the script with `bash script.sh` (both lines don't help). – bogec Apr 29 '21 at 15:56
1

At the beginning of the ~/.bashrc file usually can be found two lines as:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

This line aborts the inclusion for scripts which is not recommended anyway. For portability issues, you usually write the full command or define the alias in the script itself.

caylee
  • 921
  • 6
  • 12