which
is actually a bad way to do things like this, as it makes guesses about your environment based on $SHELL
and the startup files (it thinks) that shell uses; not only does it sometimes guess wrong, but you can't generally tell it to behave differently. (which
on my Ubuntu 10.10 doesn't understand --skip-alias
as mentioned by @SiegeX, for example.) type
uses the current shell environment instead of poking at your config files, and can be told to ignore parts of that environment, so it shows you what will actually happen instead of what would happen in a reconstruction of your default shell.
In this case, type -P
will bypass any aliases or functions:
$ type -P vim
/usr/bin/vim
You can also ask it to peel off all the layers, one at a time, and show you what it would find:
$ type -a vim
vim is aliased to `vim -X'
vim is /usr/bin/vim
(Expanding on this from the comments:)
The problem with which
is that it's usually an external program instead of a shell built-in, which means it can't see your aliases or functions and has to try to reconstruct them from the shell's startup/config files. (If it's a shell built-in, as it is in zsh
but apparently not bash
, it is more likely to use the shell's environment and do the right thing.)
type
is a POSIX-compliant command which is required to behave as if it were a built-in (that is, it must use the environment of the shell it's invoked from including local aliases and functions), so it usually is a built-in.
It isn't generally found in csh
/tcsh
, although in most modern versions of those which
is a shell builtin and does the right thing; sometimes the built-in is what
instead, and sometimes there's no good way to see the current shell's environment from csh
/tcsh
at all.
An alias should effectively not (in general) do more than change the default options of a command. It is nothing more than simple text replacement on the command name. It can't do anything with arguments but pass them to the command it actually runs. So if you simply need to add an argument at the front of a single command, an alias will work. Common examples are
# Make ls output in color by default.
alias ls="ls --color=auto"
# make mv ask before overwriting a file by default
alias mv="mv -i"
A function should be used when you need to do something more complex than an alias but that wouldn't be of use on its own. For example, take this answer on a question I asked about changing grep
's default behavior depending on whether it's in a pipeline:
grep() {
if [[ -t 1 ]]; then
command grep -n "$@"
else
command grep "$@"
fi
}
It's a perfect example of a function because it is too complex for an alias (requiring different defaults based on a condition), but it's not something you'll need in a non-interactive script.
If you get too many functions or functions too big, put them into separate files in a hidden directory, and source them in your ~/.bashrc
:
if [ -d ~/.bash_functions ]; then
for file in ~/.bash_functions/*; do
. "$file"
done
fi
A script should stand on its own. It should have value as something that can be re-used, or used for more than one purpose.
Best Answer
Personally, I have these in my bashrc and use them all the time:
You can then navigate around on the command-line a bit like a browser.
cd
changes the directory.back
goes to the previous directory that youcd
ed from. Andflip
will move between the current and previous directories without popping them from the directory stack. Overall, it works great.The only real problem that I'm aware of is the fact that it's then a set of commands that I'm completely used to but don't exist on anyone else's machine. So, if I have to use someone else's machine, it can be a bit frustrating. If you're used to just using
pushd
andpopd
directly, you don't have that problem. And while if you just aliascd
put notpopd
, you won't have the issue ofback
not existing, you'll still have the problem thatcd
doesn't do quite what you expect on other machines.I would note, however, that your particular implementation of
cd
doesn't quite work likecd
in that the normalcd
by itself will go to your home directory, but yours doesn't. The version that I have here doesn't have that problem. Mine also appendsDIRSTACK
onto the front of thedirs
print out, but that's more a matter of personal taste more than anything.So, as I said, I use these aliases all the time and have no problem with them. It's just that it can be a bit frustrating to have to use another machine and then find them not there (which shouldn't be surprising, but they're one of those things that you use so often that you don't think about them, so having them not work like you're used to can still be surprising).