Why bash alias doesn't work in scripts? [duplicate] - bash

This question already has answers here:
How to use aliases defined in .bashrc in other scripts?
(6 answers)
Closed 2 years ago.
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!

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
}

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

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.

Related

shell program to build a stack in Linux ubuntu [duplicate]

How to set a global environment variable in a bash script?
If I do stuff like
#!/bin/bash
FOO=bar
...or
#!/bin/bash
export FOO=bar
...the vars seem to stay in the local context, whereas I'd like to keep using them after the script has finished executing.
Run your script with .
. myscript.sh
This will run the script in the current shell environment.
export governs which variables will be available to new processes, so if you say
FOO=1
export BAR=2
./runScript.sh
then $BAR will be available in the environment of runScript.sh, but $FOO will not.
When you run a shell script, it's done in a sub-shell so it cannot affect the parent shell's environment. You want to source the script by doing:
. ./setfoo.sh
This executes it in the context of the current shell, not as a sub shell.
From the bash man page:
. filename [arguments]
source filename [arguments]
Read and execute commands from filename in the current shell
environment and return the exit status of the last command executed
from filename.
If filename does not contain a slash, file names in PATH are used to
find the directory containing filename.
The file searched for in PATH need not be executable. When bash is not
in POSIX mode, the current directory is searched if no file is found
in PATH.
If the sourcepath option to the shopt builtin command is turned off,
the PATH is not searched.
If any arguments are supplied, they become the positional parameters
when filename is executed.
Otherwise the positional parameters are unchanged. The return status
is the status of the last command exited within the script (0 if no
commands are executed), and false if filename is not found or cannot
be read.
source myscript.sh is also feasible.
Description for linux command source:
source is a Unix command that evaluates the file following the command,
as a list of commands, executed in the current context
#!/bin/bash
export FOO=bar
or
#!/bin/bash
FOO=bar
export FOO
man export:
The shell shall give the export attribute to the variables corresponding to the specified names, which shall cause them to be in the environment of subsequently executed commands. If the name of a variable is followed by = word, then the value of that variable shall be set to word.
A common design is to have your script output a result, and require the cooperation of the caller. Then you can say, for example,
eval "$(yourscript)"
or perhaps less dangerously
cd "$(yourscript)"
This extends to tools in other languages besides shell script.
In your shell script, write the variables to another file like below and source these files in your ~/.bashrc or ~/.zshrc
echo "export FOO=bar" >> environment.sh
In your ~/.bashrc or ~/.zshrc, source it like below:
source Path-to-file/environment.sh
You can then access it globally.
FOO=bar
export FOO

Uppercased command aliasing in bash script?

I have a script I'm trying to make at least somewhat platform-independent. Because I can't count on the PATHs or shell aliases of my users (some of whom have been known to create aliases matching "reserved words" meaningful to the shell), I've taken to aliasing all non-builtin shell commands with uppercase equivalents. This works fine when I do it semi-manually, e.g.
AWK=/usr/bin/awk
DATE=/bin/date
GREP=/bin/grep
, but not so well when I try it in a function by iterating through an array of commands:
createAliases() {
COMMANDS=(awk chmod date echo git mkdir)
WHICH=/usr/bin/which
for command in ${COMMANDS[#]}; do
${command^^}=$($WHICH ${command})
done
}
, which produces errors like AWK=/usr/bin/awk: No such file or directory. Is my attempt to use the string^^ up-casing mechanism interfering with the variable assignment? It looks like the shell is actually trying to run the (aliased) commands, which is not what I want.
Any assistance is appreciated!
The following seems to work:
shopt -s expand_aliases
createAliases() {
COMMANDS=(awk chmod date echo git mkdir)
WHICH=/usr/bin/which
for command in ${COMMANDS[#]}; do
alias ${command^^}=$($WHICH ${command})
done
}
Prefixing the assigment with alias actually registers the desired aliases.
The line shopt -s expand_aliases enables you to then use these alias from anywhere in the script, according to https://www.thegeekdiary.com/how-to-make-alias-command-work-in-bash-script-or-bashrc-file/

After alias, script didn't get variable [duplicate]

This question already has answers here:
How to use aliases defined in .bashrc in other scripts?
(6 answers)
Closed 2 years ago.
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!
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
}
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
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.

How do create an alias in shell scripts? [duplicate]

This question already has answers here:
using alias in shell script? [duplicate]
(7 answers)
Closed 2 years ago.
Definin an alias on Linux system is very simple.
From the following example we see that: the I_am_only_ls_alias alias command gives us the output as ls command
# alias I_am_only_ls_alias=ls
# I_am_only_ls_alias
Output:
file file1
But when I trying to do the same in bash script (define alias I_am_only_ls_alias), I get I_am_only_ls_alias: command not found.
Example of my bash script:
alias_test.bash
#!/bin/bash
alias I_am_only_ls_alias=ls
I_am_only_ls_alias
Run the bash script - alias_test.bash
/tmp/alias_test.bash
Output:
/tmp/: line 88: I_am_only_ls_alias: command not found
So, first I want to ask:
Why doesn't bash recognize the command I_am_only_ls_alias as an alias?
And what do I need to do in order to define aliases inside a bash script? Is it possible?
From the bash man page:
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 this should work:
#!/bin/bash
shopt -s expand_aliases
alias I_am_only_ls_alias=ls
I_am_only_ls_alias
Scripts usually use functions, not aliases.
Barmar's answer is the correct one for including an alias, but it's likely that you'll actually find a Bash function to be more flexible/useful.
For example this is materially the same as the alias version, but can be expanded much more easily:
timp#helez:~/tmp$ cat test.sh
#!/usr/bin/bash
function i_am_only_an_ls_func {
ls "$#"
}
i_am_only_an_ls_func
timp#helez:~/tmp$ ./test.sh
0600871h.html
[snip]
timp#helez:~/tmp$
The $# is irrelavent in this example, but it means that anything after i_am_only_an_ls_func will be added after the ls command, since $#, $1, $2, etc contain the arguments to the function, much the same as for a normal script. (Note that $0 is still the name of the parent script not the function)
Aliases cannot be defined in shell script that you execute - their effect will be gone once shell process finished execution.
You can, however, define aliases in your ~/.bashrc or in separate shell script that you source from (but not execute!). In that case, aliases are imported into already running shell process, and thus survive and actually work as you would expect.

how to write commands into shell script?

I want to write a shell script to execute commands like "export JAVA_HOME=....."
How could I write a script?
I try:
#!/bin/sh
echo "test"
export PATH=$JAVA_HOME/bin:$PATH
export AWS_AUTO_SCALING_HOME=/usr/local/CLI
export PATH=$PATH:$AWS_AUTO_SCALING_HOME/bin
export AWS_CREDENTIAL_FILE=/usr/local/CLI/credential-file-path.template
But the commands are not executed.
But the commands are not executed.
They are executed, but in a sub-shell. The parent shell does not inherit these values.
Instead of executing your script, source it:
source /path/to/myscript.sh
Or
. /path/to/myscript.sh
Further reading: What is the difference between executing a bash script and sourcing a bash script?
How are you executing your script? If you use:
$ script.sh
the environment is set for the duration of the script, but the parent shell is completely unaffected by this (Unix is not DOS!).
To get the results of the commands into your shell, use:
$ . script.sh
or in Bash you can use:
$ source script.sh
(This is a synonym for the . (dot) command, which has been in shells since the Bourne shell. The source command was in C shell first, then added to Bash.)
These read the script into the current process. Any environment variable settings affect the current process. Your profile is effectively read using . $HOME/.profile, for example.
Note that the file for the dotted command is searched for in the directories on $PATH, but the file only needs to be readable, not executable too.
Have you tried setting permission to execute the file??
chmod +x filename

Resources