bash autocompletion with alias command - bash

in my ~/.bashrc, for git I have this alias
alias g='git'
how I can use the autocompletion of git with my alias g ?

Add the following line to your .bashrc file:
complete -F XXX g
where XXX should be replaced by the value following -F in the output of the following command:
complete -p git
(It is likely, but not guaranteed, that this will be _git.)

Related

run alias from another shell script

I have an alias like alias cdpy="cd python" in my .bash_profile and I have sourced it. But I am still not able to use that in another shell script of mine, which is called pygitup.
I googled it and got some answers like adding shopt -s expand_aliases. I have added it to the pygitup but it still doesn't work. Am I using it wrong? This is how I use it:
# some code
shopt -s expand_aliases
cdpy
# some code
If you run pygitup from your environment with a leading "dot space", it will inherit your shell's configuration, including aliases.
A simple example with a bash script:
user#pc:~ $ alias e='echo alias is set'
user#pc:~ $ e
alias is set
user#pc:~ $ vim pygitup.sh
user#pc:~ $ cat pygitup.sh
#!/bin/bash
e
user#pc:~ $
user#pc:~ $ ./pygitup.sh
./pygitup.sh: line 2: e: command not found
user#pc:~ $
user#pc:~ $
user#pc:~ $ . ./pygitup.sh # <--- notice the leading dot
alias is set
user#pc:~ $
Aliases are not inherited by external commands, so there's no alias to expand. You'd have to source the file that defines the alias again in your script:
# some code
shopt -s expand_aliases
source ~/.bash_profile
cdpy
# some code

How to "hide" an executable from a bash script?

I want to test the output of a bash script when one of the executables it depends on is missing, so I want to run that script with the dependency "hidden" but no others. PATH= ./script isn't an option because the script needs to run other executables before it reaches the statement I want to test. Is there a way of "hiding" an executable from a script without altering the filesystem?
For a concrete example, I want to run this script but hide the git executable (which is its main dependency) from it so that I can test its output under these conditions.
You can use the builtin command, hash:
hash [-r] [-p filename] [-dt] [name]
Each time hash is invoked, it remembers the full pathnames of the commands specified as name arguments, so they need not be searched for on subsequent invocations. ... The -p option inhibits the path search, and filename is used as the location of name. ... The -d option causes the shell to forget the remembered location of each name.
By passing a non-existent file to the -p option, it will be as if the command can't be found (although it can still be accessed by the full path). Passing -d undoes the effect.
$ hash -p /dev/null/git git
$ git --version
bash: /dev/null/git: command not found
$ /usr/bin/git --version
git version 1.9.5
$ hash -d git
$ git --version
git version 1.9.5
Add a function named git
git() { false; }
That will "hide" the git command
To copy #npostavs's idea, you can still get to the "real" git with the command builtin:
command git --version
Since we know the program is running in bash, one solution is to - instead of "hiding" the program - emulate the behaviour of bash in this circumstance. We can find out what bash does when a command isn't found quite easily:
$ bash
$ not-a-command > stdout 2> stderr
$ echo $?
127
$ cat stdout
$ cat stderr
bash: not-a-command: command not found
We can then write this behaviour to a script with the executable name, such as git in the question's example:
$ echo 'echo >&2 "bash: git: command not found" && exit 127' > git
$ chmod +x git
$ PATH="$PWD:$PATH" git
$ echo $?
127
$ cat stdout
$ cat stderr
bash: git: command not found

Jenkins can't access shell alias

I have configured a Jenkins job to source a bash script that sources another bash script which adds an alias to the .bashrc of its user and sources the .bashrc itself, and then original script tries to use that alias (set by the second). However, it cannot seem to find the alias it has just created. I am not using any scripting plugins aside from using a "Send files or execute commands over SSH" build step to source the script.
The job does this:
source ./test_script.sh
test_script.sh looks like this:
echo "In test_script.sh"
echo $USER
echo $HOME
source ./setup_env.sh
echo "\nBack in test_script.sh"
alias foo
foo
And finally, setup_env.sh looks like this:
echo "\nIn setup_env.sh"
echo "alias foo=\"echo foobar\"" >> $HOME/.bashrc
source $HOME/.bashrc 2>/dev/null
cat $HOME/.bashrc
The output I receive from the Jenkins job looks like this:
In test_script.sh
my_user
/home/my_user
\nIn setup_env.sh
...all of my bashrc...
alias foo="echo foo"
\nBack in test_script.sh
alias foo='echo foo'
./test_script.sh: line 7: foo: command not found
I don't understand why this is happening, when I can happily run it myself on the command-line and watch it succeed. Why can't Jenkins use the new alias, when it can obviously find it (as demonstrated by the output of the alias foo command)?
For anyone else who's having this problem, you may need to set the expand_aliases shell option, which seems to be off by default with Jenkins:
shopt expand_aliases # check if it's on
shopt -s expand_aliases # set expand_aliases option to true
shopt expand_aliases # it should be on now
# test with a simple alias, should print 1
alias x="python -c 'print 1'"
x
The \n that is showing in the output of your echo commands
suggest this is not running under bash, as you may be expecting.
Please check the setting of your jenkins user
(or any other user that you run Jenkins with) -
especially the setting of the default shell.
To test this, add one of those lines at the beginning of your script:
env
or
env | grep -i shell
Should also consider making sure your scripts run under the correct shell,
by adding the "shebang" line as the first line in each script.
In the case of 'bash', for example, you should add the following first line:
#!/bin/bash
(it is not a comment, despite what the auto-syntax-highlighter may think...)

How to find out where alias (in the bash sense) is defined when running Terminal in Mac OS X

How can I find out where an alias is defined on my system? I am referring to the kind of alias that is used within a Terminal session launched from Mac OS X (10.6.3).
For example, if I enter the alias command with no parameters at a Terminal command prompt, I get a list of aliases that I have set, for example:
alias mysql='/usr/local/mysql/bin/mysql'
However, I have searched all over my system using Spotlight and mdfind in various startup files and so far can not find where this alias has been defined. ( I did it a long time ago and didn't write down where I assigned the alias).
For OSX, this 2-step sequence worked well for me, in locating an alias I'd created long ago and couldn't locate in expected place (~/.zshrc).
cweekly:~ $ which la
la: aliased to ls -lAh
cweekly:~$ grep -r ' ls -lAh' ~
/Users/cweekly//.oh-my-zsh/lib/aliases.zsh:alias la='ls -lAh'
Aha! "Hiding" in ~/.oh-my-zsh/lib/aliases.zsh. I had poked around a bit in .oh-my-zsh but had overlooked lib/aliases.zsh.
you can just simply type in alias on the command prompt to see what aliases you have. Otherwise, you can do a find on the most common places where aliases are defined, eg
grep -RHi "alias" /etc /root
First use the following commands
List all functions
functions
List all aliases
alias
If you aren't finding the alias or function consider a more aggressive searching method
Bash version
bash -ixlc : 2>&1 | grep thingToSearchHere
Zsh version
zsh -ixc : 2>&1 | grep thingToSearchHere
Brief Explanation of Options
-i Force shell to be interactive.
-c Take the first argument as a command to execute
-x -- equivalent to --xtrace
-l Make bash act as if invoked as a login shell
Also in future these are the standard bash config files
/etc/profile
~/.bash_profile or ~/.bash_login or ~/.profile
~/.bash_logout
~/.bashrc
More info: http://www.heimhardt.com/htdocs/bashrcs.html
A bit late to the party, but I was having the same problem (trying to find where the "l." command was aliased in RHEL6), and ended up in a place not mentioned in the previous answers. It may not be found in all bash implementations, but if the /etc/profile.d/ directory exists, try grepping there for unexplained aliases. That's where I found:
[user#server ~]$ grep l\\. /etc/profile.d/*
/etc/profile.d/colorls.csh:alias l. 'ls -d .*'
/etc/profile.d/colorls.csh:alias l. 'ls -d .* --color=auto'
/etc/profile.d/colorls.sh: alias l.='ls -d .*' 2>/dev/null
/etc/profile.d/colorls.sh:alias l.='ls -d .* --color=auto' 2>/dev/null
The directory isn't mentioned in the bash manpage, and isn't properly part of where bash searches for profile/startup info, but in the case of RHEL you can see the calling code within /etc/profile:
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null 2>&1
fi
fi
done
Please do check custom installations/addons/plugins you have added, in addition to the .zshrc/.bashrc/.profile etc files
So for me: it was git aliased to 'g'.
$ which g
g: aliased to git
Then I ran the following command to list all aliases
$ alias
I found a whole lot of git related aliases that I knew I had not manually added.
This got me thinking about packages or configurations I had installed. And so went to the
.oh-my-zsh
directory. Here I ran the following command:
$ grep -r 'git' . |grep -i alias
And lo and behold, I found my alias in :
./plugins/git/git.plugin.zsh
I found the answer ( I had been staring at the correct file but missed the obvious ).
The aliases in my case are defined in the file ~/.bash_profile
Somehow this eluded me.
For more complex setups (e.g. when you're using a shell script framework like bash-it, oh-my-zsh or the likes) it's often useful to add 'alias mysql' at key positions in your scripts. This will help you figure out exactly when the alias is added.
e.g.:
echo "before sourcing .bash-it:"
alias mysql
. $HOME/.bash-it/bash-it.sh
echo "after sourcing bash:"
alias mysql
I think that maybe this is similar to what ghostdog74 meant however their command didn't work for me.
I would try something like this:
for i in `find . -type f`; do # find all files in/under current dir
echo "========"
echo $i # print file name
cat $i | grep "alias" # find if it has alias and if it does print the line containing it
done
If you wanted to be really fancy you could even add an if [[ grep -c "alias" ]] then <print file name>
The only reliable way of finding where the alias could have been defined is by analyzing the list of files opened by bash using dtruss.
If
$ csrutil status
System Integrity Protection status: enabled.
you won't be able to open bash and you may need a copy.
$ cp /bin/bash mybash
$ $ codesign --remove-signature mybash
and then use
sudo dtruss -t open ./mybash -ic exit 2>&1 | awk -F'"' '/^open/ {print substr($2, 0, length($2)-2)}'
to list all the files where the alias could have been defined, like
/dev/dtracehelper
/dev/tty
/usr/share/locale/en_CA.UTF-8/LC_MESSAGES/BASH.mo
/usr/share/locale/en_CA.utf8/LC_MESSAGES/BASH.mo
/usr/share/locale/en_CA/LC_MESSAGES/BASH.mo
/usr/share/locale/en.UTF-8/LC_MESSAGES/BASH.mo
/usr/share/locale/en.utf8/LC_MESSAGES/BASH.mo
/usr/share/locale/en/LC_MESSAGES/BASH.mo
/Users/user/.bashrc
/Users/user/.bash_aliases
/Users/user/.bash_history
...
Try: alias | grep name_of_alias
Ex.: alias | grep mysql
or, as already mentioned above
which name_of_alias
In my case, I use Oh My Zsh, so I put aliases definition in ~/.zshrc file.

ssh command execution doesn't consider .bashrc | .bash_login | .ssh/rc? [duplicate]

This question already has answers here:
Why aliases in a non-interactive Bash shell do not work
(4 answers)
Closed 6 years ago.
I am trying to execute a command remotely over ssh, example:
ssh <user>#<host> <command>
The command which needs to be executed is an alias, which is defined in .bashrc, e.g.
alias ll='ls -al'
So what in the end the following command should get executed:
ssh user#host "ll"
I already found out that .bashrc only gets sourced with interactive shell, so in .bash_login I put:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
and I also tried to define the alias directly in .bash_login.
I also tried to put the alias definition / sourcing of .bashrc in .bash_profile and also in .ssh/rc. But nothing of this works.
Note that I am not able to change how the ssh command is invoked since this is a part of some binary installation script. The only thing I can modify is the environment. Is there any other possibility to get this alias sourced when the ssh command is executed? Is there some ssh configuration which has to be adapted?
From the man pages of bash:
Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt
There are a couple ways to do this, but the simplest is to just add the following line to your .bashrc file:
shopt -s expand_aliases
Instead of:
ssh user#host "bash -c ll"
try:
ssh user#host "bash -ic ll"
to force bash to use an "interactive shell".
EDIT:
As pointed out here about non-interactive shells..
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
# execution returns after this line
Now, for every alias in your bashrc file say i have:
alias ll="ls -l"
alias cls="clear;ls"
Create a file named after that alias say for ll:
user#host$ vi ssh_aliases/ll
#inside ll,write
ls -l
user#host$ chmod a+x ll
Now edit .bashrc to include:
# If not running interactively, don't do anything
[ -z "$PS1" ] && export $PATH=$PATH:~/ssh_aliases
This does the job.. although I am not sure if it is the best way to do so
EDIT(2)
You only need to do this for aliases, other commands in bashrc will be executed as pointed out by David "you must have executable for ssh to run commands".
an alternative to alias that will be visible in all script is
EXPORT & EXECUTE VARIABLE
# shortcut to set enviroment to insensitive case
export go_I="shopt -s nocasematch"
Now in any script you can use
#!/bin/bash
$go_I # go Insensitive
[[ a == A ]] # evaluates TRUE ( $? == 0)
$go_C # maibe want to go back to casesensitive
it's useful to place all shortcuts/aliases in /path/to/my_commands and edit /etc/bash.bashrc
source /path/to/my_commands
Open file ~/.bash_profile. If this file does not exist create one in the home directory and add the below line
source = $HOME/.bashrc
exit your ssh and login agian and you should get the .bashrc settings working for you.

Resources