Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

It's taken me almost 10 years of Linux usage to ask this question. It was all trial and error and random late-night internet surfing.

But people shouldn't need 10 years for this. If I were just starting out with Linux, I'd want to know: When to alias, when to script, and when to write a function?

Where aliases are concerned, I use aliases for very simple operations that don't take arguments.

alias houston='cd /home/username/.scripts/'

That seems obvious. But some people do this:

alias command="bash bashscriptname"

(and add it to the .bashrc file)

Is there a good reason to do that? I'm trying really hard, but I genuinely can't think of any circumstances in which I'd want to do that. So, if there is an edge case where that would make a difference, please answer below.

Because that's where I would just put something in my PATH and chmod +x it, which is another thing that came after years of Linux trial-and-error.

Which brings me to the next topic. For instance, I added a hidden folder (.scripts/) in the home directory to my PATH by just adding a line to my .bashrc (PATH=$PATH:/home/username/.scripts/), so anything executable in there automagically autocompletes.

If I needed to.

I don't really do that, though, do I? I would only use that for languages that are not the shell, like Python.

If it's the shell, I can just write a function inside the very same .bashrc:

funcname () {
  somecommand -someARGS $@
}

As I stated, I found a lot of this out through trial and error. And I only truly saw the beauty of functions when my computer died and I was forced to use the computers of the people around me when they weren't using them.

Instead of moving a whole directory of scripts from computer to computer, I ended up just replacing everyone else's .bashrc with my own, since they had never even made a single modification.

But did I miss anything?

So, what would you tell a beginning Linux user about when to alias, when to script, and when to write a function?

If it's not obvious, I'm assuming the people who answer this will make use of all three options. If you only use aliases, or only use scripts, or only use functions, -- or if you only use aliases and scripts or aliases and functions or scripts and functions --this question isn't really aimed at you.

share|improve this question
4  
possible duplicate of bash functions vs scripts –  Gilles Feb 5 '12 at 22:35
1  
+1 for the stating explicitly all the subsets of {alias, script, function} at which this question does not aim. +1 for the childlike faith that it was OK for you to omit the null subset. –  Thomas L Holaday Aug 26 '13 at 15:16
add comment

10 Answers

up vote 94 down vote accepted

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.

share|improve this answer
6  
Take a look at my answer as well for more concrete differences between functions and scripts. Basically, functions and aliases are for frequently used simple things that you want to be stored in memory, while scripts are for more rarely used commands that you don't mind reading from disk every time. Whether or not a new forked process is needed also makes a slight difference if you run a command several thousand times in a for loop. –  jw013 Feb 7 '12 at 0:55
add comment

The other answers provide some soft general guidelines based on personal taste, but ignore many pertinent facts that one should consider when deciding between scripts, functions, or aliases.

Aliases and Functions ¹

  • The entire contents of aliases and functions are stored in the shell's memory.
  • A natural consequence of this is aliases and functions can only be used by the current shell, and not by any other programs you may invoke from the shell like text editors, scripts, or even child instances of the same shell.
  • Aliases and functions are executed by the current shell, i.e. they run within and affect the shell's current environment.² No separate process is necessary to run an alias or function.

Scripts

  • Shells do not keep scripts in memory. Instead, scripts are read from the files where they are stored every time they are needed. If the script is found via a $PATH search, many shells store a hash of its path name in memory to save time on future $PATH look-ups, but that is the extent of a script's memory footprint when not in use.
  • Scripts can be invoked in more ways than functions and aliases can. They can be passed as an argument to an interpreter, like sh script, or invoked directly as an executable, in which case the interpreter in the shebang line (e.g. #!/bin/sh) is invoked to run it. In both cases, the script is run by a separate interpreter process with its own environment separate from that of your shell, whose environment the script cannot affect in any way. Indeed, the interpreter shell does not even have to match the invoking shell. Because scripts invoked this way appear to behave like any ordinary executable, they can be used by any program.

    Finally, a script can be read and run by the current shell with ., or in some shells, source. In this case, the script behaves much like a function that is read on-demand instead of being constantly kept in memory.

Application

Given the above, we can come up with some general guidelines for whether to make something a script or function / alias.

  • Do other programs besides your shell need to be able to use it? If so, it has to be a script.

  • Do you only want it to be available from an interactive shell? It's common to want to change the default behavior of many commands when run interactively without affecting external commands / scripts. For this case, use an alias / function set in the shell's "interactive-mode-only" rc file (for bash this is .bashrc).

  • Does it need to change the shell's environment? Both a function / alias or a sourced script are possible choices.

  • Is it something you use frequently? It's probably more efficient to keep it in memory, so make it a function / alias if possible.

  • Conversely, is it something you use only rarely? In that case, there's no sense having it hog memory when you don't need it, so make it a script.


¹ While functions and aliases have some important differences, they are grouped together because functions can do everything aliases can. Aliases can not have local variables nor can they process arguments, and they are inconvenient for anything longer than one line.

² Every running process in a Unix system has an environment consisting of a bunch of variable=value pairs which often contain global configuration settings, like LANG for the default locale and PATH for specifying executable search path.

share|improve this answer
11  
IMHO This is the best answer. –  Luc M Feb 8 '12 at 18:51
3  
The question/answer format is a great idea. I might steal that. ;-) –  Mikel May 9 '12 at 15:46
    
+1 this is an excellent answer –  César Sep 20 '12 at 19:21
    
@jw013 thanks for the detailed answer. –  Russell Silva Nov 21 '13 at 16:05
    
+1 for extra knowledge about what "bashrc" is. –  jgomo3 Nov 30 '13 at 20:38
show 2 more comments

I think it's up to each person's taste. For me the logic goes like this:

  • First I try to make an alias, because it's the simplest.
  • If the thing is too complicated to fit in one line, I try to make it a function.
  • When the function starts to grow beyond a dozen of lines I put it in a script.

There is really nothing to restrict you from doing something that works.

share|improve this answer
5  
I often skip the function option, and make a script right away. But I agree that it is partly a matter of taste –  Bernhard Feb 5 '12 at 15:00
    
A function begins to make sense if you need it in several scripts. –  Nils Feb 10 '12 at 21:45
add comment

At least partially it's a matter of personal taste. On the other hand there are some clear functional distinctions:

  • aliases: only suitable for simple text replacements, no arguments/parameters
  • functions: easy to write/use, full shell scripting capability, only available inside bash
  • scripts: more or less like functions, but available (callable) outside of bash as well

Looking at shell scripting I've done the last few years I have more or less stopped writing aliases (because they all tend to grow into functions over time) and do scripts only if they need to be available also from non-bash environments.

PS: As for alias command="bash bashscriptname" I don't actually see any reason to do this. Even if bashscriptname is not in $PATH, a simple alias c=/path/to/script would be enough.

share|improve this answer
1  
+1, scripts callable out of the shell. –  ysdx Feb 8 '12 at 9:56
add comment

One other thing that I don't believe has been brought up: a function executes in the context of the invoking process, whereas a scrip forks a new shell.

This could be important for performance -- function is faster, since it doesn't fork() and exec(). In normal circumstances, the difference is trivial, but if you are debugging a system that is out of memory and is page-thrashing, it could make a big difference.

Also, if you want to modify your current shell environment, you should use a function. For example, a function could change the command lookup $PATH for the current shell, but a script cannot, because it operates on a fork/exec copy of $PATH.

share|improve this answer
add comment

Script and alias and script and function aren't mutually exclusive. You can and do store aliases and functions in scripts.

Scripts are just code which is made persistent. Useful functions and aliases, which you like to use in future are stored in scripts. However, a script is often a collection of more than one function.

Since aliases aren't parametrized, they are very limited; usually to define some default parameters.

A function is a separate unit of code, a well defined concept of a few lines of code, which can't seperated into smaller, useful parts, which can be reused directly or other by other functions.

share|improve this answer
add comment

Just to add a few notes:

  • Only separate script can be used with sudo (like if you need to edit a system file), for example:
sudo v /etc/rc.conf  #where v runs vim in a new terminal window;
  • Only aliases or functions could replace system commands under same name (assuming that you add your scripts dir to the end of PATH, which I think is advisable for safety in case of accidental or malevolent creating of script with name identical to a system command), for example:
alias ls='ls --color=auto'  #enable colored output;
  • Aliases and functions take less memory and time for execution, but take time to load (since shell has to interpret them all before showing you prompt). Take this into account if you run new shell processes regularily, for example:
# pressing key to open new terminal
# waiting for a few seconds before shell prompt finally appears.

Other than that, you could use the simplest form possible, i.e. first consider alias, then function, then script.

share|improve this answer
4  
Aliases can also be used with sudo. But first you need alias sudo='sudo '. –  Mikel May 9 '12 at 15:32
add comment

If it should be very fast, make it an alias or a function.

If it should be usable outside your preferred shell, make it a script.1

If it takes arguments, make it a function or a script.

If it needs to contain special characters, make it an alias or a script.2

If it needs to work with sudo, make it an alias or a script.3

If you want to change it easily without logging out and in, a script is easier.4

Footnotes

1 Or make it an alias, put it in ~/.env and set export ENV="$HOME/.env", but it's complicated to make it work portably.

2 Function names must be identifiers, so they must start with a letter, and may only contain letters, digits, and underscores. For example, I have an alias alias +='pushd +1'. It can't be a function.

3 And add the alias alias sudo='sudo '. Ditto any other command such as strace, gdb, etc. that takes a command as its first argument.

4 See also: fpath. Of course you can also do source ~/.bashrc or similar, but this often has other side effects.

share|improve this answer
1  
I didn't know you could alias + in bash. Interestingly, after testing I discovered that in bash you can make + an alias but not a function, as you say, but zsh is the reverse - + can be a function but not an alias. –  Kevin May 9 '12 at 18:42
    
In zsh you have to write alias -- +='some command here'. –  Mikel May 10 '12 at 1:07
    
Somehow, I don't think aliasing + is portable. See the POSIX spec on Alias Names –  jw013 Aug 23 '12 at 18:08
add comment

When to write a script ...

  • Scripts assemble software components (aka. tools, commands, processes, executables, programs) into more complex components, which may themselves be assembled into still more complex components.
  • Scripts are usually made executable so they can be called by name. When called, a new subprocess is spawned for the script to run in. Copies of any exported variables and/or functions are passed by value to the script. Changes to those variables do not propagate back to the parent script.
  • Scripts may also be loaded(sourced) as if they were part of the calling script. This is analogous to what some other languages call "import" or "include". When sourced, they execute within the existing process. No subprocess is spawned.

When to write a function ...

  • Functions are effectively pre-loaded shell scripts. They perform a bit better than calling a separate script, but only if it must be read from mechanical disk. Today's proliferation of flashdrives, SSDs and Linux's normal caching in unused RAM make that improvement largely unmeasurable.
  • Functions serve as bash's principle means of achieving modularity, encapsulation and reuse. They improve the clarity, reliability and maintainability of scripts.
  • The syntax rules for calling a function are identical to that of calling an executable. A function with the same name as an executable would be invoked instead of the executable.
  • Functions are local to the script they are in. They are invisible to the process that calls that script (e.g. commandline, another script or a program).
  • Functions may be exported (copied by value) so they can be used inside called scripts. Thus, functions only propagate to child processes, never parents.
  • Functions create reusable commands that are often assembled into libraries (a script with only function definitions) to be sourced by other scripts.

When to write an alias ...

share|improve this answer
add comment
  1. alias for single line text replacement
  2. scripts for anything more.
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.