16

I have a very wierd case... If I run a script with /bin/bash, it can't recognize aliases that I set even inside the script. And the most strange thing is

$ cat -n test.sh
    1 #!/bin/bash
    2 alias somecommand='ls -alF'
    3 alias
    4 somecommand
$ ./test.sh
alias somecommand='ls -alF'
./test.sh: line 4: somecommand: command not found

... as shown above, if I run the command "alias" in the script it turns out that bash has taken somecommand into the aliases, but if I run the somecommand itself it will still not be recognized!

Everything is right if I use the command "sh" to run the script.. so is it a bug of bash? Or is there something I'm missing?

Any help is appreciated!

1
  • 3
    Avoid aliases in scripts. Define and use real bash functions. Commented May 31, 2017 at 14:54

6 Answers 6

21

Simply don't use aliases in scripts. It makes little sense to use a feature designed for interactive use in scripts. Instead, use functions:

somecommand () {
    ls -alF
}

Functions are much more flexible than aliases. The following would overload the usual ls with a version that always does ls -F (arguments are passed in $@, including any flags that you use), pretty much as the alias alias ls="ls -F" would do:

ls () {
    command ls -F "$@"
}

The command here prevents the shell from going into an infinite recursion, which it would otherwise do since the function is also called ls.

An alias would never be able to do something like this:

select_edit () (
    dir=${1:-.}
    if [ ! -d "$dir" ]; then
        echo 'Not a directory' >&2
        return 1
    fi
    shopt -s dotglob nullglob
    set --
    for name in "$dir"/*; do
        [ -f "$name" ] && set -- "$@" "$name"
    done
    select file in "$@"; do
        "${EDITOR:-vi}" "$file"
        break
    done
)

This creates the function select_edit which takes directory as an argument and asks the user to pick a file in that directory. The picked file will be opened in an editor for editing.

The bash manual contains the statement

For almost every purpose, aliases are superseded by shell functions.

3
  • Thank you... but the thing is that I want to alias the main part of a long command, and use it each time with different suffix(some more options, with objects in the end)... can functions handle that too?
    – nichen
    Commented May 31, 2017 at 7:31
  • @nichen See updated answer.
    – Kusalananda
    Commented May 31, 2017 at 7:42
  • ...that's really nice! I didn't understand all the codes you wrote but got the idea, thanks a lot :)
    – nichen
    Commented May 31, 2017 at 8:02
10

To use interactive features like alias within a bash script you have to run it in an interactive bash shell. For that change the first line to include a -i . So your new script file becomes

#!/bin/bash -i
alias somecommand='ls -alF'
alias
somecommand 
1
  • Had to add the alias for gksu (since Ubuntu has removed it from 18.04 onwards) and it is needed for launching certain GUI applications needing graphical authentication check prior to doing sudo. The bash native function method didn't seem to work, but this method did.
    – bdutta74
    Commented Jan 13, 2019 at 18:11
7

Kind of a duplicate of a previous question however the answers there are kind of wordy. The short answer is that, for occult reasons, by default bash doesn't look at aliases defined inside scripts. You have to explicitly tell it to do so via a shopt -s expand_aliases line at the top of said script. Do that and then your script will find somecommand.

2
  • I read that question but thought it was a different case because the alias was defined in ~/.bashrc and was supposed to be used in another script...
    – nichen
    Commented May 31, 2017 at 7:23
  • Yes, it is slightly different in the way that you describe but the principle is the same. That script was running ~/.bashrc when it starts up, (inside line 1 of the script) and then ignoring all _alias_es created inside script running shells.
    – Nadreck
    Commented May 31, 2017 at 13:47
6

Just add shopt -s expand_aliases after first line

#!/bin/bash
shopt -s expand_aliases
alias somecommand='ls -alF'
alias
somecommand

This will output

$ /tmp/alias.sh 
alias somecommand='ls -alF'
total 111044
drwxr-xr-x  4 sobi3ch sobi3ch     4096 Aug 22 14:27 ./
drwxr-xr-x 31 sobi3ch sobi3ch     4096 Aug 23 10:19 ../

Aliases for default are only for interactive shells (from man bash)

expand_aliases

If set, aliases are expanded as described above under ALIASES. This option is enabled by default for interactive shells.

1

Use shopt -sq expand_aliases, for example, this code in UTF-8 encoding:

#!/bin/bash

function запрещать() {
    if [ $1 -eq 3 ]
    then
        echo -n "Запрещено. Код ошибки: "
        echo `expr 2 \* 3 \* 47`
    else
        echo -n "."
        запрещать `expr $1 + 1`
    fi
}

#function запретить() {
#   запрещать 1
#}

shopt -sq expand_aliases
alias запретить='запрещать 1'

запретить
2
  • Does this add anything to the previous answers?
    – RalfFriedl
    Commented Dec 7, 2018 at 18:13
  • 1
    @RalfFriedl, this code supplements sobi3ch and Nadreck answers, illustrating the alias definition for multi-line functions, not for calling the external shell programs. Commented Dec 7, 2018 at 18:33
0
source your_script

instead of execute as a new shell, just source your script and alias will be accepted

1
  • Where do you suggest the script to be sourced?
    – nath
    Commented Mar 29 at 13:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .