10

The last line of my .bash_profile is:

alias cp=/usr/local/bin/gcp

However that is being squashed by the entry in my $PATH :

$which cp
/bin/cp
11:54:32/OCspark $type cp
cp is aliased to `/usr/local/bin/gcp'

I had thought that aliases override the PATH .. ?

WestCoastProjects
  • 3,465
  • 11
  • 51
  • 90
  • 1
    For the record: technically, aliases do ***not*** override any values in the `PATH` envar. – can-ned_food Aug 30 '17 at 13:57
  • Obligatory caution: In general, it is not good practice to rename common commands. This can bite you two ways. 1) If you work on another system and use your command by habit, you will get the unexpected behavior of the native command. 2) If anyone else uses your system, even to advise/help you solve a problem, they will get the unexpected behavior of your customization. Custom commands are fine, just don't name them the same as common existing ones. – Joe Sep 05 '17 at 10:24
  • @joe Actually it is more of the *reverse* here: the os/x version of *cp* lacks options from *nix so it does not behave as expected (except to those who *like* the hobbled mac version) – WestCoastProjects Sep 05 '17 at 15:44

2 Answers2

21

The which command returns only executables: it knows nothing about aliases, since it is an external program, and there is no mechanism for passing alias information to a child process.

If you enter the command type -a cp you will see all possible interpretations, in order of preference. This includes any alias, since type is a bash internal command.

It is important to realise that an alias will not be interpreted by a sub-process, such as a script or an interactive editor which has an option to run system commands.

If you make cp a function, then your version will run in scripts, though not from other programs:

cp() { /usr/local/bin/gcp "$@"; }

If you want your cp to work everywhere, add $HOME/bin at the head of your PATH list and point $HOME/bin/cp to point to it:

ln -s /usr/local/bin/gcp $HOME/bin/cp

This makes a symbolic link, though you can make it a slightly more efficient hard link (omit -s), but this will normally need root permissions (sudo ln ...). Creating a function and adding to the PATH variable will be done in one of the bash start-up scripts, with user permissions.

AFH
  • 17,300
  • 3
  • 32
  • 48
  • 1
    Although on CentOS (and AIUI all RedHat) the standard profile (unless overridden) creates an _alias_ for `which` that runs `/usr/bin/which` with input piped from the output of `alias` and an option that tells it to read that input and use it to show an alias if it matches the command. See https://unix.stackexchange.com/questions/10525/how-to-use-which-on-an-aliased-command – dave_thompson_085 Aug 30 '17 at 02:09
  • @dave_thompson_085 - Interesting comment: I've not used those distributions. I use Ubuntu and I can get much the same effect by simply aliasing `which` to `type`. Then `which -a` operates like the external program, with the addition of the alias and function definitions. In general I don't `alias which=type`, because I like to use `$(which ProgName)` when I want to force the use of an external program, bypassing any alias or function definitions. – AFH Aug 30 '17 at 10:28
  • 1
    Hard links can't cross filesystems, so the non-symbolic `ln` suggestion will only work if your home directory is on the same filesystem as `/usr/local/bin`. It will also behave oddly if you update `gcp`, as your hard link will probably still refer to the old version. – Useless Aug 30 '17 at 12:30
  • @Useless - Valid points, which is part of why I edited my answer to suggest a symbolic link first, though I think that the permissions are probably the most important consideration. As for updating `gcp`, it will depend whether the update is done by opening and writing or by deleting and re-creating. Note that it is immaterial whether an absolute or relative source path is used to create a hard link, while a symbolic link usually needs an absolute path. Links are used extensively in the OS, and they are mostly symbolic. – AFH Aug 30 '17 at 12:47
  • Of course, aliases can be expanded in scripts if the shell option `expand_aliases` is set. – can-ned_food Aug 30 '17 at 13:55
  • 1
    @can-ned_food - It's not as simple as setting it in the current shell: it has to be set in each script, together with importing the aliases. – AFH Aug 30 '17 at 18:33
  • @AFH Good point. I do all that with my `BASH_ENV` shell variable value. A tad slow, yes, but it gives me a good platform with fewer surprises. – can-ned_food Aug 31 '17 at 00:41
14

Aliases are internal to the shell. Other programs won't know about them.

which is not a Bash builtin (it is a builtin in some other shells, e.g. zsh). Since which has no privileged information into Bash's aliases, which just looks through PATH for the given term.

type, on the other hand is a Bash builtin, so it can report on aliases.

8bittree
  • 2,900
  • 1
  • 17
  • 28