11

At first I was looking for the reason that which doesn't output anything after giving it certain programs as an argument, e.g. cd.

From what I've found here, the reason probably is that cd on my machine is a function, which is confirmed by running type cd.

TLDR: But as normal programs that which can locate thanks to $PATH variable are placed in one of those $PATH folders, where are functions or scripts like cd stored?

user@linuxmchine:~$ type cd
cd is a function
cd () 
{ 
    __zsh_like_cd cd "$@"
}
  • I get cd is a shell builtin. Take a look at the man page for your shell (zsh?) – Xen2050 Dec 29 '14 at 22:16
  • 1
    Check out unix.stackexchange.com/questions/85249/… The problem is that which is a legacy command that should not be used - especially because of things like this question. – Joe Jan 7 '15 at 23:50
12

User defined functions

Typically bash functions are permanently stored in a bash start-up script.

  • System-wide start-up scripts: /etc/profile for login shells, and /etc/bashrc for interactive shells.
  • User define start-up scripts: ~/.bash_profile for login shells, and ~/.bashrc for interactive shells.
  • More information on interactive/login shells can be found in the bash man page in the INVOCATION section.

User defined shell functions are loaded dynamically in a hash (or lookup table) when bash starts. From the bash source file variable.c the definition for the table is:

/* The list of shell functions that the user has created, or that came from
   the environment. */
HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;

User defined functions can be listed with the bash declare command, other shells still use typeset. In bash declare has superceded the typeset command.

declare -f

The functions exist in memory for the lifetime of the bash shell.

Shell defined (builtin) functions

These are common functions such as echo, printf, cd and :. They are compiled into a library which is linked into the bash executable. Building the definitions into the executable saves time compared to loading an external definition. Definitions for these functions (held in .def source files which are parsed into C source) are held in the builtins directory of bash source.

A useful aside: for information on a shell builtin command use help <command>. e.g.

help                # list all builtins
help declare        # info and options for declare
help -m declare     # gives man style information for declare
  • Thank you for that excerpt answer. This is exactly what I've been looking for. Do you think there's a tool to follow bash functions creating process or something like typeset that would show what file/script caused the creation/change of a function? – Gabrijel Šimunović Dec 30 '14 at 14:49
  • I don't know of any such tool - it would be a useful option to the declare or typeset command to display the source file of a function definition. I think it's a software engineering issue. Recently found a shell function defined in a .alias file - not what I was expecting! – suspectus Dec 30 '14 at 15:17
8

Shell functions are stored in the memory of the shell (or, perhaps, in undocumented temporary files).  They don't exist in any usable way until the shell starts (e.g., when you login to a CLI, or start a shell window such as xterm) and they are defined (e.g., by reading .bashrc, .bash_profile, or something similar) and they cease to exist when the shell terminates.

  • 1
    The ephemeral nature of something you type at the prompt is important. My vote goes to this answer. If you type cd () { pwd; builtin cd "$@"; } at the prompt then the only place that is stored is in the memory of your currently running shell. (My example is Bash but the same principle applies to any shell.) – tripleee Dec 30 '14 at 5:34
6

cd and other common commands like echo, type & alias are so called builtins .

Builtin commands are contained within the shell itself and different shells may have different built in commands.

  • 4
    I don't know if it might be worth emphasizing that the executable code for builtin commands like cd is contained within the shell program itself, e.g. within the file /bin/bash if that is your shell. (I do think your wording here is clear, but I've seen people get confused by all sorts of things.) – David Z Dec 30 '14 at 1:58
1

The Super User question Finding the definition of a bash function is closely related to this one.  User HairOfTheDog provided this answer (paraphrased):

The following commands will report the location (filename and line number) of a function’s definition.  Assuming a function named foo,

# Turn on extended shell debugging
shopt -s extdebug

# Display the function’s name, line number and fully qualified source file
declare -F foo

# Turn off extended shell debugging
shopt -u extdebug

For example, the output of these commands might be:

foo 32 /source/private/main/developer/cue.pub.sh

The above might work only in bash, and not in POSIX shells in general.

Thanks to Blue Raspberry for finding this!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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