alias in a script - linux

In linux, if I put a command in a script that contains an alias, I see that it doesn't get expanded. How can I fix that? I am using bash.

According the the TLDP page about aliases, you need to use the line shopt -s expand_aliases in your code to expand aliases. The example below produced the expected output, but without the shopt line it just printed "my_ls: command not found":
#!/bin/bash
shopt -s expand_aliases
alias my_ls='ls -lrt'
echo "Trying my_ls"
my_ls
exit

If you want your shell aliases to be available in a script, you must manually include them. If they are defined in ~/.bashrc, put a line
. ~/.bashrc
after the #!/bin/sh line in your script. This will execute the contents of .bashrc in the context of your script.

Enabling posix mode (such as by calling bash as sh or with the command (set -o posix) 2>/dev/null && set -o posix should do the trick.
Even then, be aware that aliases are expanded as they are parsed, and the ordering between parsing and execution is poorly defined. For example
alias foo=echo; foo bar
or
{
alias foo=echo
foo bar
}
will try to run foo as the alias is not defined at parse time yet. Also, some shells parse the whole input of an eval or . (source) before executing any of it.
So the only portable and reliable way to use aliases in scripts is to define them and then eval or . the code that uses them.

Related

bash shell script alias expansion not working inside if statement [duplicate]

I can't get expand_aliases to take effect in bash. I've tried a lot of different things, and nothing works.
Here's the simple test case:
/bin/bash -c 'shopt -s expand_aliases; alias cdtmp="cd /tmp"; alias; cdtmp; pwd;'
And the output:
$ /bin/bash -c 'shopt -s expand_aliases; alias cdtmp="cd /tmp"; alias; cdtmp; pwd;'
alias cdtmp='cd /tmp'
/bin/bash: cdtmp: command not found
/home/user
$ /bin/bash --version
GNU bash, version 3.2.25(1)-release (i686-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
(Yes, I'm using shopt instead of the -O option to bash, just to prove it's being done.)
Any ideas?
Aliases aren't available on the same line or in the same function where they are defined.
From the Bash man page:
The rules concerning the definition and use of aliases are somewhat
confusing. Bash always reads at least one complete line of input
before executing any of the commands on that line. Aliases are
expanded when a command is read, not when it is executed. Therefore,
an alias definition appearing on the same line as another command does
not take effect until the next line of input is read. The commands
following the alias definition on that line are not affected by the new
alias. This behavior is also an issue when functions are executed.
Aliases are expanded when a function definition is read, not when the
function is executed, because a function definition is itself a com‐
pound command. As a consequence, aliases defined in a function are not
available until after that function is executed. To be safe, always
put alias definitions on a separate line, and do not use alias in com‐
pound commands.
For almost every purpose, aliases are superseded by shell functions.
The Bash Reference Manual says
For almost every purpose, shell functions are preferred over aliases.
instead of the last sentence above [emphasis mine]. I consider aliases to be a command-line convenience rather than something that should be used in scripts (including those which consist solely of bash -c one-liners).
I came late for 10 years.
you can use the eval to make the alias cdtmp expand again.
/bin/bash -c 'shopt -s expand_aliases; alias cdtmp="cd /tmp"; alias; eval cdtmp; pwd;'
will give you output
alias cdtmp='cd /tmp'
/tmp
try /bin/bash -O expand_aliases -c 'xx'

Need an elegant way to overload a command in a Bash script dynamically created and called by another tool

There have been a lot of posts about how to overload commands in Bash, either by creating an alias or function, or just changing the script itself or how it is called; these methods make perfect sense to me but don't apply to the problem I'm trying to solve.
It is common in the semiconductor industry to work with EDA tools that provide API commands inside a Tcl interpreter; in my case the EDA tool generates a Bash script, then executes it one API call, so I only have access to the script after the script executed and cannot modify how it is called since that happens under the hood; there is also no blessed method for modifying the commands of interest that are written into the script.
What complicates this further is that this script is generated and called by the EDA tool inside a Singularity container; also, the command that is being called resides in a different EDA tool container, so this command 'vsim' must be transformed into an ssh call to our workload manager (slurm). Example:
vsim <args>
Must be converted to:
ssh <some-host> <ssh-options> "srun <srun-options> vsim <args>"
Again, setting an alias or function called 'vsim' in the parent shell didn't work for me; the alias/function was not inherited by the subprocess (this is difficult for me to accept). I also tried creating a symlink called 'vlog' that pointed at a static dispatcher script; this worked by I'd rather not hard code the path to the dispatcher as a file path; I would rather use a variable, like vlog -> .../<resource>/$VERSION/bin/dispatch_for_flows, but symlinks are not dynamic.
I'm thinking that I should still use the symlink approach but instead of pointing at the dispatcher, I'd point at a wrapper that does a single line exec of an interpolated path to the dispatcher, but I'm still not believing that setting an alias didn't solve the problem. For years I wrote Csh scripts with full paths to commands to get around user aliases; with Bash, it looks like aliases are not inherited ever, even with the shopt 'expanand_alias' on in the parent shell or even in /etc/profile. What am I missing here?
Can someone get the example below to work? I'd like the script to inherit the alias from the parent shell and execute without the "command not found" error, without modification to the script or how it is called. Again, I have no access to the script before it is executed and can't control how it is called; bash is the parent shell, bash is the script, and I do have root access on the OS so I could change the version of bash if neccessary (using 4.4.19(1)-release (x86_64-redhat-linux-gnu))
$ alias hello='echo world'
$ hello
world
$ shopt | grep expand_aliases
expand_aliases on
$ cat test.bash
#!/usr/bin/bash
set -x
alias
shopt | grep expand_aliases
shopt -s expand_aliases
shopt | grep expand_aliases
hello
$ ./test.bash
+ alias
+ shopt
+ grep expand_aliases
expand_aliases off
+ shopt -s expand_aliases
+ shopt
+ grep expand_aliases
expand_aliases on
+ hello
./test.bash: line 7: hello: command not found
Can someone get the example below to work?
No that's not possible with aliases - you can't export an alias. But you can export a function.
$ hello() { echo world; }
$ export -f hello
$ ./test.bash
world
You can create a custom command in PATH:
$ printf "%s\n" "#!/bin/bash" "echo world" > /usr/local/bin/hello
$ chmod +x /usr/local/bin/hello
and similarly add a custom command and add new path with the command to PATH and export.

Bash script to go to directory and perform commands gives "Command not found" [duplicate]

This question already has answers here:
How to use aliases defined in .bashrc in other scripts?
(6 answers)
Closed 2 years ago.
My alias defined in a sample shell script is not working. And I am new to Linux Shell Scripting.
Below is the sample shell file
#!/bin/sh
echo "Setting Sample aliases ..."
alias xyz="cd /home/usr/src/xyz"
echo "Setting done ..."
On executing this script, I can see the echo messages. But if I execute the alias command, I see the below error
xyz: command not found
am I missing something ?
source your script, don't execute it like ./foo.sh or sh foo.sh
If you execute your script like that, it is running in sub-shell, not your current.
source foo.sh
would work for you.
You need to set a specific option to do so, expand_aliases:
shopt -s expand_aliases
Example:
# With option
$ cat a
#!/bin/bash
shopt -s expand_aliases
alias a="echo b"
type a
a
$ ./a
# a is aliased to 'echo b'
b
# Without option
$ cat a
#!/bin/bash
alias a="echo b"
type a
a
$ ./a
./a: line 3: type: a: not found
./a: line 4: a: command not found
reference: https://unix.stackexchange.com/a/1498/27031 and https://askubuntu.com/a/98786/127746
sourcing the script source script.sh
./script.sh will be executed in a sub-shell and the changes made apply only the to sub-shell. Once the command terminates, the sub-shell goes and so do the changes.
OR
HACK: Simply run following command on shell and then execute the script.
alias xyz="cd /home/usr/src/xyz"
./script.sh
To unalias use following on shell prompt
unalias xyz
If you execute it in a script, the alias will be over by the time the script finishes executing.
In case you want it to be permanent:
Your alias is well defined, but you have to store it in ~/.bashrc, not in a shell script.
Add it to that file and then source it with . .bashrc - it will load the file so that alias will be possible to use.
In case you want it to be used just in current session:
Just write it in your console prompt.
$ aa
The program 'aa' is currently not installed. ...
$
$ alias aa="echo hello"
$
$ aa
hello
$
Also: From Kent answer we can see that you can also source it by source your_file. In that case you do not need to use a shell script, just a normal file will make it.
You may use the below command.
shopt -s expand_aliases
source ~/.bashrc
eval $command
Your alias has to be in your .profile file not in your script if you are calling it on the prompt.
If you put an alias in your script then you have to call it within your script.
Source the file is the correct answer when trying to run a script that inside has an alias.
source yourscript.sh
Put your alias in a file call ~/.bash_aliases and then, on many distributions, it will get loaded automatically, no need to manually run the source command to load it.

How load custom bash aliases in NodeJS script?

I have bash script
#!/bin/bash
shopt -s expand_aliases
. my_custom_aliases # load aliases
alias foo # show alias definition
foo # run alias
and it's working as I want
$ ./alias.sh
alias foo='echo barrr'
barrr
but now I would like to do the same thing in nodejs script.
I've try something like this with ShellJS package
#! /usr/bin/env node
var shell = require("shelljs");
shell.exec('shopt -s expand_aliases', {shell: '/bin/bash'});
shell.exec('. my_custom_aliases', {shell: '/bin/bash'});
shell.exec('alias foo', {shell: '/bin/bash'});
shell.exec('foo', {shell: '/bin/bash'});
(my_custom_aliases obviously are in the same directory)
but it's only throwing on me this
$ node am.js
/bin/bash: line 0: alias: foo: not found
/bin/bash: foo: command not found
So my question is: How can I load custom aliases from file and be able to use them from inside the node script?
I'm not convinced that you are doing sane things (if you really do, functions might be better than aliases anyway), but the problem is that you are running four separate shells, each of which then exits and loses whatever state you had created.
To run a single shell, you want something like
shell.exec('shopt -s expand_aliases \n . my_custom_aliases \n alias foo; foo',
{shell: '/bin/bash'});
As outlined in comments below, because expand_aliases needs to be active when a line with an alias is first parsed, you need a newline rather than a semicolon as the first and second statement separator.

Wrong BASH-Variable return from a bash script

I'd like to check the value of $HISTFILE (or any similar BASH-Variable) by a bash script. On the command console 'echo $HISTFILE' is the way I normally go, but from inside a bash script, which only includes:
#!/bin/bash
echo $HISTFILE
gives an empty line instead of showing $HOME/$USER/.bash_history (or similar return values). My questions are:
What is the reason for doing so (since I never had such trouble using bash scripts) and
how can I check the value of BASH-Variables like $HISTFILE from inside a bash script?
Many thanks in advance. Cheers, M.
HISTFILE is only set in interactive shells; scripts run in non-interactive shells. Compare
$ bash -c 'echo $HISTFILE' # non-interactive, no output
$ bash -ic 'echo $HISTFILE' # interactive, produces output
/home/me/.bash_history
However, forcing the script to run in an interactive shell will also cause your .bashrc file to be sourced, which may or may not be desirable.

Resources