I am trying to use the solution of using sudo on my existing aliases as covered in many existing answers already and i am so confused as to why it is not working
alias sudo='sudo '
I keep all my aliases in .bash_aliases. Inside .bash_aliases I have this
function _test {
echo 'test!'
}
alias test='_test'
I reload the .bashrc each time; source .bashrc but when I run sudo test I always get
sudo: _test: command not found
The only strange thing that happens is that I get the following on reload and not on a new terminal
dircolors: /home/MYHOME/.dircolors: No such file or directory
but i feel this is a red herring.
As l0b0 says, aliases cannot be used in this way in bash.
However, you can pass a function through (and really, there's basically never a good reason to use an alias instead of sticking to functions alone).
_test() {
echo 'test!'
}
sudo_test() {
sudo bash -c "$(declare -f _test)"'; _test "$#"' sudo_test "$#"
}
...will define a command sudo_test that runs the function _test via sudo. (If your real-world version of this function calls other functions or requires access to shell variables, add those other functions to the declare -f command line, and/or add a declare -p inside the same command substitution to generate a textual description of variables your function needs).
To run an alias like alias_name it must be exactly the first word in the command, so sudo alias_name will never work. Ditto 'alias_name', \alias_name and other things which eventually expand to the alias name.
Related
I am trying to use the solution of using sudo on my existing aliases as covered in many existing answers already and i am so confused as to why it is not working
alias sudo='sudo '
I keep all my aliases in .bash_aliases. Inside .bash_aliases I have this
function _test {
echo 'test!'
}
alias test='_test'
I reload the .bashrc each time; source .bashrc but when I run sudo test I always get
sudo: _test: command not found
The only strange thing that happens is that I get the following on reload and not on a new terminal
dircolors: /home/MYHOME/.dircolors: No such file or directory
but i feel this is a red herring.
As l0b0 says, aliases cannot be used in this way in bash.
However, you can pass a function through (and really, there's basically never a good reason to use an alias instead of sticking to functions alone).
_test() {
echo 'test!'
}
sudo_test() {
sudo bash -c "$(declare -f _test)"'; _test "$#"' sudo_test "$#"
}
...will define a command sudo_test that runs the function _test via sudo. (If your real-world version of this function calls other functions or requires access to shell variables, add those other functions to the declare -f command line, and/or add a declare -p inside the same command substitution to generate a textual description of variables your function needs).
To run an alias like alias_name it must be exactly the first word in the command, so sudo alias_name will never work. Ditto 'alias_name', \alias_name and other things which eventually expand to the alias name.
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/
I'm trying to find out how a specific command is defined. I've checked all locations of $PATH and could not find any file that is named like my command, so it seems to be something else.
Here is an example using nvm, that is not an executable:
me#MacBook:~$ which cat
/bin/cat
me#MacBook:~$ which nvm
me#MacBook:~$ nvm --version
0.33.8
which nvm simply returns nothing.
What is the equivalent of "which" for commands like this in unix based systems?
The command you are looking for is type.
type nvm will show how the shell will interpret the command, so unlike which it'll show aliases, functions and unexported paths too.
Here is an answer to a simiar question that advises against the use of which for reasons unrelated to the point in question.
That said, your assumption that which can only see executables is wrong.
It does not, however, see functions and aliases by default.
That's why the manpage of which says:
The recommended way to use this utility is by adding an alias (C shell) or shell function (Bourne
shell) for which like the following:
[ba]sh:
which () {
(alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $#
}
export -f which
If you define this function in your .bashrc and re-source it, you should be able to do
which -a
and it should give you functions and aliases as well.
However, watch out, if maybe some profile or bashrc already defined something for which, that takes precedence (you could find that out, with type -a which btw).
If I define a script, a function and an alias, called something I get with type -a:
type -a something
something is aliased to `echo "something"'
something is a function
something ()
{
echo "function something"
}
something is /home/myself/bin/something
While which -a after creating the function gives me:
which -a something
alias something='echo "something"'
/usr/bin/echo
/bin/echo
something ()
{
echo "function something"
}
~/bin/something
My .bashrc file contains:
# mkdir, cd into it
function mkcd ()
{
mkdir -p "$*"
cd "$*"
}
When I type mkcd in shell I get mkcd: Command not found.
when I type source ~/.bashrc I get an error:
Badly placed ()'s.
by the way, my text editor (emacs) is recognising the code as Shell-script[tcsh].
How do I fix this?
If you can accept the restriction that you have to pass the name of the directory to be created as the first argument, it should look like this:
# mkdir, cd into it
function mkcd ()
{
mkdir -p "$#"
cd "$1"
}
You need to run source ~/.bashrc to see it working (or alternatively start a new shell).
Three comments on that function. This will work mostly. To catch some corner cases:
Either use function mkcd { ...; } or mkcd() { ...; }. The first is compatible with ksh, but only if you drop the (). The mkcd() notation is the standard POSIX notation.
Even mkdir -p can fail, so make the cd conditional on mkdir.
Finally, you want exactly one argument to mkdir and cd. Use only one argument, and test that it has a value with the :? modifier in parameter substitution. This will stop the function from sending you $HOME.
Together:
function mkcd
{
mkdir -p "${1:?}" && cd "${1}"
}
Put that in your .bashrc and open a new shell. Type type mkcd. This should respond with:
mkcd is a function, followed by its definition.
I ran your mkcd function on bash 4.2.45 and linux 3.8.0 and it worked as expected. Logging on in a fresh window or running
source ~/.bashrc
in your existing window should define the function for you. If it does not work you'll get an error message like:
mkcd: command not found
While hek2mgl's suggestion is not necessary to make it work, it does make it make more sense since you're only going to cd to one directory.
As commented by Henk Langeveld and hek2mgl: "Wrong shell. Badly placed ()'s is a message produced by tcsh. Switch to bash or ksh."
I thought that opening a terminal on ubuntu entered straight into bash environment. In fact, as commented below, "a Terminal will start a copy of your login shell as defined in /etc/passwd". By typing ps -p $$ in terminal, I realise mine is set to tcsh, the C shell. In that case, one needs to type bash to get into bash environment.
Then source ~/.bashrc compiles the definition for mkcd.
I'd like to execute a particular bash function when I enter a new directory. Somethink like:
alias cd="cd $# && myfunction"
$# doesn't work there, and adding a backslash doesn't help. I'm also a little worried about messing with cd, and it would be nice if this worked for other commands which changed directory, like pushd and popd.
Any better aliases/commands?
Aliases don't accept parameters. You should use a function. There's no need to execute it automatically every time a prompt is issued.
function cd () { builtin cd "$#" && myfunction; }
The builtin keyword allows you to redefine a Bash builtin without creating a recursion. Quoting the parameter makes it work in case there are spaces in directory names.
The Bash docs say:
For almost every purpose, shell functions are preferred over aliases.
The easiest solution I can come up with is this
myfunction() {
if [ "$PWD" != "$MYOLDPWD" ]; then
MYOLDPWD="$PWD";
# strut yer stuff here..
fi
}
export PROMPT_COMMAND=myfunction
That ought to do it. It'll work with all commands, and will get triggered before the prompt is displayed.
There are a few other versions of this out there, including
smartcd, which I wrote, and has a ton of features including templating and temporary variable saving
ondir, which is smaller and much simpler
Both of these support both bash and zsh
I've written a ZSH script utilizing the callback function chpwd to source project specific ZSH configurations. I'm not sure if it works with Bash, but I think it'll be worth a try. If it doesn't find a script file in the directory you're cd'ing into, it'll check the parent directories until it finds a script to source (or until it reaches /). It also calls a function unmagic when cd'ing out of the directory, which allows you to clean up your environment when leaving a project.
http://github.com/jkramer/home/blob/master/.zsh/func/magic
Example for a "magic" script:
export BASE=$PWD # needed for another script of mine that allows you to cd into the projects base directory by pressing ^b
ctags -R --languages=Perl $PWD # update ctags file when entering the project directory
export PERL5LIB="$BASE/lib"
# function that starts the catalyst server
function srv {
perl $BASE/script/${PROJECT_NAME}_server.pl
}
# clean up
function unmagic {
unfunction src
unset PERL5LIB
}