Memra

Where your shell looks, and where your settings live

◈ 11 cards

PATH resolution order, choosing between a login file and an rc file, and the four different questions which, whereis, type and command -v answer.

Internal, then external, then a search

When you type a word at a prompt, the shell resolves it in a fixed order. First it checks whether the word is an alias, then a shell function, then a built-in command (cd, echo and alias are built in — cd has to be, because a separate process could not change your shell's directory). Only if it is none of those does the shell go looking for an external command, and it looks in the directories named by the search path, left to right, first match wins.

In the Bourne family — sh, ksh, bash, and therefore on your Linux or WSL2 system by default — the variable is PATH and its entries are separated by colons. In the C shell family it is the lowercase path, and its entries are separated by spaces inside parentheses. Different name, different delimiter, same idea; assignments have tested exactly that difference.

Worked example — shadowing a command, and losing it again

Suppose /usr/bin/python3 is the system interpreter and you want your own build in front of it.

echo $PATH
mkdir -p ~/bin
PATH=$HOME/bin:$PATH
type -a python3

Before the change, type -a python3 reports /usr/bin/python3. After it, the same command lists your copy first and the system one second, because type -a walks the whole path and shows every hit in search order. Run python3 and you get yours: first match wins, and the loser is not consulted at all.

Now open a second terminal and run type -a python3 there. It reports only the system copy. Your change lived in one shell's memory and no other process inherited it — the assignment was made in a shell that the new terminal is not a child of. Log out and back in and even the original shell has forgotten.

To make it stick, the assignment has to be executed by every new shell, which means it has to live in a start-up file:

echo 'PATH=$HOME/bin:$PATH' >> ~/.profile

Single quotes are doing real work in that line: they stop the shell from substituting the value now and write the literal text into the file, so the expansion happens when the file is read at each login.

Which file, and why it matters

The distinction the assignments test is login file versus rc file.

A login file.profile for the Bourne family, .login for the C shell — runs once, when you log in. It is the right place for anything that is inherited by child processes: PATH, umask, and exported environment variables. Setting them once at login is enough, because every shell you start afterwards is a descendant and inherits them.

An rc file.bashrc for bash, .cshrc for csh — runs for every shell that starts. It is the right place for things that are not inherited: aliases, shell functions, the prompt string, and shell options. An alias defined in .profile will not exist in a sub-shell, which is exactly the bug the textbook's question set asks about.

On most Linux distributions bash reads ~/.bash_profile at login if it exists and falls back to ~/.profile if it does not, and the distribution's default ~/.bash_profile usually sources ~/.bashrc so that a login shell also gets the aliases. That last line is a convention, not a rule — if aliases are missing in your login shell, that is the line to look for.

Four commands, four different questions

type -a name is a shell built-in and the only one of the four that can see aliases, functions and built-ins. It answers what will this word mean, and what else could it have meant. command -v name is the POSIX-standard way to ask what will actually run, printing one answer and exiting non-zero if there is none — which makes it the one to use in a script. which name is an external program on Linux that searches only the path, so it cannot see an alias or a built-in and will happily disagree with your shell. whereis name ignores the path entirely and searches a fixed list of system directories for the binary, its source and its manual page.

Use type -a when you are asking why is this command behaving oddly, because that question is almost always answered by something which cannot see.

A dot on the path is a security smell

The textbook shows appending . to the search path without comment. Think about what that means: change into any directory a second person can write to, type ls, and if they left a file called ls there, theirs runs instead of the system one, with your privileges. With . at the front of the path it is worse still — every command you type in that directory is up for grabs. Leave it off. If you need to run a program in the current directory, say so explicitly with ./program.

FileShellWhen it runsWhat belongs in it~/.profilesh, ksh, bashlogin shells onlyPATH, umask,exported variables~/.bash_profilebashlogin shells, readinstead of .profileif presentthe same, plus aline sourcing.bashrc~/.bashrcbashevery interactiveshellaliases, functions,prompt, shelloptions~/.logincsh, tcshlogin shells onlypath, umask, setenv~/.cshrccsh, tcshevery csh thatstartsaliases, setvariablesAliases are not inherited by a child shell, which is why they belong in an rc file.
The load-bearing distinction is the middle column. Anything inherited by child processes can be set once at login; anything that is not inherited has to be set by every shell.
CommandAnswersSearchesCaveattype -a nameevery meaning theword has, in orderaliases, functions,builtins, then PATHa shell builtin —the only one thatsees aliasescommand -v namethe one thing thatwill actually runthe same,POSIX-standardsilent and non-zeroif there is nomatchwhich namethe first PATHmatchPATH onlyan external programon Linux; missesaliases andbuiltinswhereis namebinary, source andmanual page pathsa fixed list ofsystem directoriesignores your PATHentirelyOnly the first two are built into the shell, so only they can see what the shell knows.
They disagree on purpose. If a command is behaving oddly, ask type -a — the thing shadowing it is usually an alias or a function, and those are the two things which cannot see.
NORMAL ~/memra/learn/comp-325/path-startup-files-and-locating-commands utf-8 LF