Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

In my ~/.bashrc file reside two definitions:

  1. commandA, which is an alias to a longer path
  2. commandB, which is an alias to a Bash script

I want to process the same file with these two commands, so I wrote the following Bash script:


#!/bin/bash

for file in $@
    do
    commandA $file
    commandB $file
done

Even after logging out of my session and logging back in, Bash prompts me with command not found errors for both commands when I run this script.

What am I doing wrong?

share|improve this question
5  
BTW, there's no need to log in and out to have an alias recognized. You need just do source ~/.bashrc. – Tshepang Nov 25 '10 at 19:10
    
For my case I was connected by SSH agent remotely, after adding alias as I closed the SSH agent and connected again it started working. – dav Sep 6 '15 at 5:05
up vote 65 down vote accepted

First of all, as ddeimeke said, aliases by default are not expanded in non-interactive shells.

Second, .bashrc is not read by non-interactive shells unless you set the BASH_ENV environment variable.

But most importantly: don't do that! Please? One day you will move that script somewhere where the necessary aliases are not set and it will break again.

Instead set and use environment variables as shortcuts in your script:

#!/bin/bash

CMDA=/path/to/gizmo
CMDB=/path/to/huzzah.sh

for file in "$@"
do
    $CMDA "$file"
    $CMDB "$file"
done
share|improve this answer
    
That solution doesn’t work for the usual alias use cases. E.g. alias mv="mv -v --backup=numbered". – Evi1M4chine Apr 23 at 20:11
    
@Evi1M4chine: Yes, it does. At least after I reverted Gilles unnecessary edit. But it might be better to use a different variable for the parameters, anyway. – hop Apr 24 at 15:50
    
Ah, note the lack of quotes around $CMDA / $CMDB… Apart from uppercase variables being reserved for bash itself in bash, and it indeed working, that lack of quotes makes me really uneasy… Thanks anyway. – Evi1M4chine Apr 30 at 0:26
    
@Evi1M4chine: Uh, what? 1. I removed the quotes myself in the most recent edit. 2. where do you get the "reserved for bash itself" from? this would be the first I've heard of it. 3. If that makes you uneasy, how do you feel about using bash in the first place? Anyway, use a separate variable for the options as I told you. – hop Apr 30 at 17:46
    
1. From experience, unquoted variables have the bad habit of blowing up in one’s face. E.g. when the variable is empty, one expects it to have no spaces but it does, etc. Here, the latter is intended, but it still makes me uneasy. :) 2. Turns out it’s something in-between: wiki.bash-hackers.org/scripting/… → If you use uppercase variables, there’s a chance that a later version of bash uses that name itself, breaking your script. 3. Don’t worry. You seem to have mistaken my comment for criticism. It wasn’t. :) – Evi1M4chine May 1 at 21:08

If you look into the bash manpage you find:

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS below).

So put a

shopt -s expand_aliases

in your script.

Make sure to source your aliases file after setting this in your script.

shopt -s expand_aliases
source ~/.bash_aliases
share|improve this answer
1  
I placed it in my script, but it's still not working. Same error. – Zaid Sep 2 '10 at 10:29
2  
Adding shopt -s expand_aliases source ~/.bash_aliases works perfectly for me. Often there is a form of interactive shell detection in .bashrc like this: # If not running interactively, don't do anything [ -z "$PS1" ] && return @Zaid, Maybe you want to check for that in the file you sourced. – Frank Schubert Apr 4 '13 at 1:46
    
excellent! saved my scripts!! :) it is so hard to read/search/browse info and manpages in the terminal that I just gave up long ago and go search on the internet... – Aquarius Power Sep 17 '13 at 19:24
1  
Curiously, shopt -s expand_aliases doesn't have to go before the alias definition but before the alias use. Adding to @FrankSchubert: Interactive shell detection may also be done using $- which contains the options for the shell, specifically i if the shell is interactive. – valid Mar 20 '15 at 14:12
1  
this isn't a correct answer... Sourcing your aliases inside your script isn't the answer. Your ~/.bash_aliases might depend on other stuff previously loaded on an interactive shell... The closest thing I found is changing your hashbang to #!/bin/bash -li Still not perfect. Ideally you should use functions and not aliases. – Stefanos Kalantzis Feb 5 at 11:47

Aliases can't be exported so they're not available in shell scripts in which they aren't defined. In other words, if you define them in ~/.bashrc they're not available to your_script.sh (unless you source ~/.bashrc in the script, which I wouldn't recommend but there are ways to do this properly).

However, functions can be exported and would be available to shell scripts that are run from an environment in which they are defined. This can be done by placing this in your bashrc:

foo()
{
    echo "Hello World!"
}
export -f foo

As the Bash manual says, "For almost every purpose, shell functions are preferred over aliases."

share|improve this answer
[cmd line] > bash -i [your script's file path]

The i is for interactive and sources your bash profile for you.

share|improve this answer

I found sometimes bash script doesn't recognize export either. However, changing it to

#!/bin/sh

works for me.

share|improve this answer

protected by slm Apr 18 '14 at 15:08

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.