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:


for file in "$@"
    commandA $file
    commandB $file

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?

  • 13
    BTW, there's no need to log in and out to have an alias recognized. You need just do source ~/.bashrc.
    – tshepang
    Nov 25, 2010 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, 2015 at 5:05
  • An alias is a way of shortening a command. (They are only used in interactive shells and not in scripts — this is one of the very few differences between a script and an interactive shell.)
    – LF00
    Sep 12, 2019 at 10:18

5 Answers 5


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
  • 17
    I placed it in my script, but it's still not working. Same error.
    – Zaid
    Sep 2, 2010 at 10:29
  • 8
    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. Apr 4, 2013 at 1:46
  • 3
    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, 2015 at 14:12
  • 4
    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. Feb 5, 2016 at 11:47
  • 2
    Alas, this doesn't work with bash -c, for example bash -c "shopt -s expand_aliases; source my-script.sh; some-alias. Still get some-alias: command not found
    – Hubro
    Feb 17, 2022 at 23:00

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 variables as shortcuts in your script:



for file in "$@"
    $CMDA "$file"
    $CMDB "$file"
  • 7
    That solution doesn’t work for the usual alias use cases. E.g. alias mv="mv -v --backup=numbered". Apr 23, 2016 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.
    – user601
    Apr 24, 2016 at 15:50
  • 1
    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. Apr 30, 2016 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.
    – user601
    Apr 30, 2016 at 17:46
  • 1
    @alvas: the assumption is that gizmo is not on the path or there is a command with the same name but a higher priority. else you could simple set CMDA to plain gizmo in the first place.
    – user601
    Apr 5, 2017 at 9:20

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:

    echo "Hello World!"
export -f foo

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

  • 3
    While this doesn't technically answer the question, as you say you can simply replace alias commandA=... with commandA() { ... } then export commandA and you get identical behavior to the alias. So this is pretty much an identical alternative to aliases as far as I know that works great in bash scripts
    – Phylliida
    May 21, 2018 at 18:35
  • The problem here is when you need an alias that you pass lots of quoted options to. for instance as an example, alias b=bash makes it easy to do b -c "echo test | grep test" which would be difficult to do in functions.
    – Fmstrat
    Aug 13, 2019 at 16:03
  • @Fmstrat: b () { bash "$@"; } then b -c "echo test | grep test" Aug 13, 2019 at 16:10
  • This does not solve the problem when the contents of the function needs to be evaluated in the script that got the function from another script...
    – Akito
    Jan 29, 2020 at 18:10
  • @Akito: I'm not sure what you mean. It works for me. Jun 28, 2022 at 23:46
[cmd line] > bash -i [your script's file path]

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


You can also use . before your script. Run it as:

. /path/to/your/script.sh

You can check for this condition on your bash script as follows:

if [[ $- == *i* ]]
    echo "running on interactive mode. aliases will work!"
  • 2
    For a solution which avoids editing the script itself (that is why a script exists for us so it can be shared among many people) this is really great
    – demongolem
    Mar 30, 2021 at 12:22
  • 1
    Sure, I wouldn't put it into a professional production script, but I just needed something quick and scrappy +1
    – MANA624
    Aug 17, 2021 at 19:13

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