Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between alias and export (and a function!)[BASH]?

I'm surprised hasn't been asked before, but…

What is the difference between

aliasalias EXPORT='alias'

functionfunction exporter() { echo $EXPORT }

and

exportexport 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.

like image 690
Alex Gray Avatar asked Apr 19 '14 17:04

Alex Gray


People also ask

What is the difference between an alias and a function?

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.

What is alias in Bash?

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.

What does export function do in Bash?

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.

Can you export an alias Linux?

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).


2 Answers

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 exported 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).

like image 67
Gordon Davisson Avatar answered Nov 15 '22 19:11

Gordon Davisson


TL;DR:

  1. The shell evaluation order (per POSIX) for the entities in your question is:
    aliases --> variables --> command substitutions --> special built-ins --> functions --> regular built-ins
  2. Aliases do not persist across subshells, but variables (and in Bash, functions) can be made to do so with the export command.
  3. Regular built-ins can be overridden by writing functions that have the same name as the regular built-in (since functions expand before regular built-ins). (NOTE: If you're trying to add functionality to the regular built-in, call the built-in with command in your function definition so you don't accidentally create a recursive function.)
  4. Variables can be made readonly with the (special built-in) readonly command, but aliases cannot.

USE CASES:

  1. Export a variable if you need to use a variable across subshells.
  2. Make a variable 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).
  3. If you want to override or add functionality to a regular built-in, use a function.

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

  1. my_cmd is used without double-quotes (i.e. ${my_cmd}, NOT "${my_cmd}") so it isn't treated as a single string, and
  2. 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).

like image 24
A. Hendry Avatar answered Nov 15 '22 18:11

A. Hendry