I'm surprised hasn't been asked before, but…
What is the difference between
alias ⇢ alias EXPORT='alias'
function ⇢ function exporter() { echo $EXPORT }
and
export ⇢ export ALIAS='export'
and for that matter...
alias export=$(function)
(j/k)
in bash
(zsh
, et al.)
Specifically, I'd be most interested in knowing the lexical/practical difference between
alias this=that
and
export that=this
I have both forms... all over the place - and would prefer to stop arbitrarily choosing one, over the other. 😂
I'm sure there is a great reference to a "scopes and use-cases for unix shells", somewhere... but thought I'd post the question here, in the name of righteous-canonicalicism.
Functions can be used in scripts or in the console, but are more often used in scripts. Contrary to aliases, which are just replaced by their value, a function will be interpreted by the bash shell. Functions are much more powerful than aliases. They can be used to build very complex programs.
Bash aliases allow you to set a memorable shortcut command for a longer command. Bash aliases are essentially shortcuts that can save you from having to remember long commands and eliminate a great deal of typing when you are working on the command line.
Export is a built-in command of the Bash shell. It is used to mark variables and functions to be passed to child processes. Basically, a variable will be included in child process environments without affecting other environments.
You can't. By running your script you execute a new shell. Aliases will not be seen by the parent process. The only way as pointed out is using source so that the current shell processes your script file (without starting a new process).
You're asking about two very different categories of things: aliases and functions define things that act like commands; export
marks a variable to be exported to child processes. Let me go through the command-like things first:
An alias (alias ll='ls -l'
) defines a shorthand for a command. They're intended for interactive use (they're actually disabled by default in shell scripts), and are simple but inflexible. For example, any arguments you specify after the alias simply get tacked onto the end of the command; if you wanted something like alias findservice='grep "$1" /etc/services'
, you can't do it, because $1
doesn't do anything useful here.
A function is like a more flexible, more powerful version of an alias. Functions can take & process arguments, contain loops, conditionals, here-documents, etc... Basically, anything you could do with a shell script can be done in a function. Note that the standard way to define a function doesn't actually use the keyword function
, just parentheses after the name. For example: findservice() { grep "$1" /etc/services; }
Ok, now on to shell variables. Before I get to export
, I need to talk about unexported variables. Basically, you can define a variable to have some (text) value, and then if you refer to the variable by $variablename
it'll be substituted into the command. This differs from an alias or function in two ways: an alias or function can only occur as the first word in the command (e.g. ll filename
will use the alias ll
, but echo ll
will not), and variables must be explicitly invoked with $
(echo $foo
will use the variable foo, but echo foo
will not). More fundamentally, aliases and functions are intended to contain executable code (commands, shell syntax, etc), while variables are intended to store non-executable data.
(BTW, you should almost always put variable references inside double-quotes -- that is, use echo "$foo"
instead of just echo $foo
. Without double-quotes the variable's contents get parsed in a somewhat weird way that tends to cause bugs.)
There are also some "special" shell variables, that are automatically set by the shell (e.g. $HOME
), or influence how the shell behaves (e.g. $PATH
controls where it looks for executable commands), or both.
An export
ed variable is available both in the current shell, and also passed to any subprocesses (subshells, other commands, whatever). For example, if I do LC_ALL=en_US.UTF-8
, that tells my current shell use the "en_US.UTF-8" locale settings. On the other hand, if I did export LC_ALL=en_US.UTF-8
that would tell the current shell and all subprocesses and commands it executes to use that locale setting.
Note that a shell variable can be marked as exported separately from defining it, and once exported it stays exported. For example, $PATH
is (as far as I know) always exported, so PATH=/foo:/bar
has the same effect as export PATH=/foo:/bar
(although the latter may be preferred just in case $PATH somehow wasn't already exported).
It's also possible to export a variable to a particular command without defining it in the current shell, by using the assignment as a prefix for the command. For example LC_ALL=en_US.UTF-8 sort filename
will tell the sort
command to use the "en_US.UTF-8" locale settings, but not apply that to the current shell (or any other commands).
TL;DR:
aliases --> variables --> command substitutions --> special built-ins --> functions --> regular built-ins
export
command.command
in your function definition so you don't accidentally create a recursive function.)readonly
command, but aliases cannot.USE CASES:
readonly
if you don't want it changed for the life of the parent shell (once performed, this cannot be undone with unset
; you must restart the parent shell).NOTE: If you want to be sure that you're using a special or regular built-in and not someone else's function, use builtin the_builtin
, or if the shell doesn't support the builtin
command, use the POSIX comand command -p the_builtin
, where the -p
switch tells command to use the $PATH that ships with the shell by default (in case the user has overriden path).
NOTE: A variable can be made to act like an alias that also persists across subshells and cannot be changed. For example,
#! /bin/sh
my_cmd='ls -al'
export my_cmd
readonly my_cmd
will act like
#! /bin/sh
alias my_cmd='ls -al'
so long as
my_cmd
is used without double-quotes (i.e. ${my_cmd}
, NOT "${my_cmd}"
) so it isn't treated as a single string, and
IFS
is the standard space-tab-newline
and not switched to something else so that the elements of my_cmd
are globbed and each part separated by a space is evaluated as a single token (otherwise it will be evaluated as a single string).
Each shell (e.g. bash
, zsh
, ksh
, yash
, etc.) is a bit different, so be sure to review the reference manual for it (they each implement POSIX in a unique way, or sometimes not at all).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With