5

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!

  • Don't post screenshots of text, paste the actual text... – jasonwryan May 31 '17 at 6:56
  • @jasonwryan Ok... get it :) – nichen May 31 '17 at 7:12
  • Avoid aliases in scripts. Define and use real bash functions. – Basile Starynkevitch May 31 '17 at 14:54
10

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 () {
    if [ ! -d "$1" ]; then
        echo 'Not a directory' >&2
        return 1
    fi
    select file in $(find "$1" -maxdepth 1 -type f); do
        if [ -f "$file" ]; then
            ${EDITOR:-vi} "$file"
            break
        fi
        echo 'No such file' >&2
    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.

  • 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 May 31 '17 at 7:31
  • @nichen See updated answer. – Kusalananda May 31 '17 at 7:42
  • ...that's really nice! I didn't understand all the codes you wrote but got the idea, thanks a lot :) – nichen May 31 '17 at 8:02
7

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 
  • 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. – icarus74 Jan 13 at 18:11
3

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.

  • 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 May 31 '17 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 May 31 '17 at 13:47
1

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.

0

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'

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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