Reputation: 3313
I need to create alias for my long command, normally I would use
alias myLongCommand="my long command"
but I need to define in an online system configuration where I can only use bash
command, I tried various combinations including:
bash -c 'alias myLongCommand="my long command"'
but unfortunately with no success, alias does not get defined.
To test success I use
bash -c myLongCommand
Upvotes: 2
Views: 2920
Reputation: 295272
# define a function
myLongCommand() { my long command; }
# export that function to the environment
export -f myLongCommand
# thereafter, that function is available in subprocesses
bash -c 'myLongCommand'
...or, to compress the actual creation into a one-liner:
myLongCommand() { my long command; }; export -f myLongCommand
Note that the definition and export needs to be done in a bash shell that is itself a parent process of the shell in which you intend the function to be used. If you use bash -c 'myLongCommand() { my long command; }; export -f myLongCommand'
, then the environment variable with the exported function lives only as long as that bash -c
instance does -- hence, it's entirely unavailable in any subsequent command.
If you wanted this to be available for all bash shells in your login session, you could put the definition and export in ~/.bash_profile
(and log out and back in), if your system is behaving per typical defaults with respect to dotfile initialization.
Multiple reasons:
bash -c 'alias foo="bar"'
sets up an alias only for that single bash instance created by the bash -c
command, and that alias is terminated when that command exits.bash -c
, don't inherit aliases from their parent processes, or read dotfiles (by default), so they start out with their alias table empty, even if an alias is defined in the (separate) shell that's invoking them.bash -c
, have alias evaluation turned off by default, as this is intended to be an interactive-use feature.Aliases are intended as a facility for interactive use. Thus, they're not by default available inside noninteractive shells at all. To enable alias expansion in a noninteractive instance of bash, one needs to run:
shopt -s expand_aliases
The other issue is actually getting that alias defined at all. Noninteractive shells don't run dotfiles by default (the name of a dotfile to run in a noninteractive shell can be placed in the ENV
or BASH_ENV
environment variable to override this), so they won't have aliases defined in ~/.bashrc
present.
# create a .env file, taking care not to fail badly if shell is not bash
# note that making noninteractive shells emit content on stderr will break some software
# ...so redirecting errors is entirely essential here, and ||: is necessary to not break
# ...any noninteractive shell (like dash or ash invocations) that doesn't support shopt
# ...when that shell is invoked with the -e argument.
cat >~/.env <<'EOF'
shopt -s expand_aliases 2>/dev/null ||: "fail gracefully w/o shopt"
alias myLongCommand="my long command" 2>/dev/null ||: "fail gracefully w/o aliases"
EOF
# point to it from your .bash_profile
cat >>~/.bash_profile <<'EOF'
export ENV=$HOME/.env
[[ -e $ENV ]] && source "$ENV"
EOF
# ...and update the already-running shell:
export ENV=$HOME/.env
source "$ENV"
...to do the above in one line:
printf '%s\n' 'shopt -s expand_aliases 2>/dev/null ||:' 'alias myLongCommand="my long command" 2>/dev/null ||:' >~/.env; printf '%s\n' 'export ENV=$HOME/.env' '[[ -e $ENV ]] && source "$ENV"' >>~/.bash_profile
Upvotes: 5
Reputation: 41987
bash -c
spaws a non-login, non-interactive instance of bash
, which does not read any session startup configuration file (unlike login/interactive sessions), hence no alias
definition available and also only exits when the command (alias myLongCommand="my long command"
in this case) exits. So presumably you won't get the alias available.
To permanently set aliases, you should use any file that shell reads when starting the session, for interactive session, bash
reads ~/.bashrc
. So if you put your alias
definition there, it will available on any interactive bash
instance:
echo 'alias myLongCommand="my long command"' >> ~/.bashrc
To make it avail;able from the running session , source
the file:
source ~/.bashrc
Now from an non-interactive (and non-login) session i.e. bash -c
you can make this alias
available by making the shell interactive too using the -i
option, so the ~/.bashrc
is read:
bash -ic 'myLongCommand'
Upvotes: 2