Skip to content
Search

Bash

lastmod 2026-11-03created 2014-09-27206 edits

Bash (Borune-again shell) is a Unix shell written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell. Released in 1989, it has been widely distributed as the default shell of operating systems such as the GNU operating system, Linux, Mac OS X, and Darwin. It has also been ported to DOS by DJGPP and Novell NetWare, and to Microsoft Windows through the distributions of Cygwin and MinGW.

Viewing previous screens

On Linux, in a text console rather than a GUI, you can view previous screens that have already scrolled past as follows.

  • Shift + Page Up: view previous screen
  • Shift + Page Down: view next screen

Alternatively, if you need to check a large amount of text one screen at a time, connect it to more with a PIP.

Category

If a command cannot be found, see the command-not-found.com page.

Recommends

Key environment variables

$(DISPLAY)

Current X Window Display location.

$(HOME)

User home directory.

$(HOSTNAME)

Host name.

$(PATH)

Command search path.

$(PS1)

Prompt setting.

$(PWD)

Current working directory.

$(SHELL)

Shell in use.

$(TERM)

Terminal type.

$(MANPATH)

man page path.

$(LS_COLORS)

Colors per file type for the ls command.

The full list of environment variables can be checked with the env command.

Key files

  • /etc/profile - system-wide environment settings and startup programs
  • /etc/bashrc - system-wide aliases and functions (bash shell settings)
  • /etc/inputrc - system-wide key bindings and other settings
  • $HOME/.bash_profile - user environment settings and startup programs (bash shell settings)
  • $HOME/.bashrc - user aliases and functions
  • $HOME/.inputrc - user key bindings and other settings

Input/output streams

Redirection
One form of IPC (Interprocess Communication)
Redirects a standard stream to a user-defined target (a file).
Pipe
One form of IPC (Interprocess Communication)
A way to pass one program's stdout to another program's stdin. In other words, it passes the output of one program as the input of another.

[command] > [filename]

Write the command output to a file.

[command] >> [filename]

Append the command output to the file.

[command] >& [filename]

Write the command output and errors to a file.

[command] >>& [filename]

Append the command output and errors to the file.

[command] >! [filename]

Write the command output to the file, ignoring whether the file already exists.

[command] >&! [filename]

Write the command output and errors to the file, ignoring whether the file already exists.

[command1] | [command2]

Run command2 using the Output of command1 as its Input.

[command] > [filename]

stdout 2 file

[command] 2> [filename]

stderr 2 file

[command] 2>&1

stdout 2 stderr

[command] &> [filename]

stderr and stdout 2 file

STDOUT and STDERR Redirection

&>word and >&word are equivalent. However, (in the author's experience) they may not work if the environment changes, such as the platform or the terminal program in use. Therefore, the following usage is recommended.

$ echo 'string' > word 2>&1

What does "2>&1" mean

Why redirection order matters.

  • command >file 2>&1 - sends stdout to the file first, then duplicates stderr to stdout → both streams go to the file
  • command 2>&1 >file - duplicates stderr to the current stdout (the console), then sends only stdout to the file → stderr is still printed to the console

Bash processes redirections in order, so pay attention to the order when writing commands

Terms

Wildcard character
A wildcard character is a symbol used to specify multiple files at once when issuing a command on a computer. Symbols such as the asterisk (*) and question mark (?) are used.

Shortcuts

Command editing shortcuts

  • Ctrl + A: move the cursor to the start of the command line
  • Ctrl + E: move the cursor to the end of the command line
  • Ctrl + U: delete from the cursor to the start of the command line
  • Ctrl + K: delete from the cursor to the end of the command line
  • Ctrl + W: delete from the cursor to the start of the word (deletes the whole word if at a word boundary)
  • Option + D: delete from the cursor to the end of the word (deletes the whole word if at a word boundary)
  • Ctrl + Y: paste previously deleted text
  • Ctrl + XX: move between the start of the command line and the current cursor position
  • Option + B: move back one word
  • Option + F: move forward one word
  • Option + C: convert to uppercase from the cursor position to the end of the word (converts the whole word if the cursor is at the start of the word)
  • Option + U: convert to uppercase from the cursor position to the end of the word
  • Option + L: convert to lowercase from the cursor position to the end of the word
  • Option + T: swap the current word with the previous word
  • Ctrl + F: move forward one character
  • Ctrl + B: move back one character
  • Ctrl + D: delete the character at the cursor
  • Ctrl + H: delete the character before the cursor
  • Ctrl + T: swap the character at the cursor with the previous character

Command recall shortcuts

  • Ctrl + R: reverse search through previous commands
  • Ctrl + J: run the currently found command
  • Ctrl + G: exit command search mode
  • Ctrl + P: recall the previous command
  • Ctrl + N: recall the next command
  • Ctrl + _: undo the last command
  • Option + .: use the last word of the previous command

Command control shortcuts

  • Ctrl + L: clear the screen
  • Ctrl + S: stop screen output (when running long commands) - related to XON/XOFF
  • Ctrl + Q: resume screen output (when stopped with Ctrl + S) - related to XON/XOFF
  • Ctrl + C: interrupt the current command
  • Ctrl + Z: suspend the current command

Bash Bang(!) shortcuts

  • !!: run the last command
  • !blah: run the most recent command starting with 'blah'
  • !blah:p: print the most recent command starting with 'blah' and add it to the command history
  • !$: use the last word of the previous command (same as Option + .)
  • !$:p: print the word that '!$' would substitute
  • !*: use everything except the first word of the previous command (e.g., after entering 'find some_file.txt /', '! *' returns 'some_file.txt /')
  • !*:p: print what '!*' would substitute

Metacharacters

>

Output redirection that writes standard output to a file.

>>

Output redirection that appends standard output to the end of a file.

<

Input redirection that reads standard input from a file.

*

Filename substitution wildcard that matches zero or more characters.

?

Filename substitution wildcard that matches a single character.

[...]

Filename substitution wildcard that matches any one of the characters between the brackets.

|

Pipe symbol that sends the output of one process to the input of another.

;

Used for command sequencing.

<nowiki>

</nowiki>

&&

Conditional execution that runs if the previous command succeeds.

&

Runs the command in the background. 1 (e.g. ffserver &) You can also use parallel.

#

# Comments out all characters following the character.

$

Variable access.

ETC

  • \: when placed before a command, specifies that the original command be used instead of an Alias.2 (ex. \ls -la)

TIP

  • !!: re-run the last executed command.
  • !-2: re-run the second-to-last executed command. The number can be changed.
  • !foo: run the most recent command starting with foo. (e.g. !ls)
  • !foo:p: Print out the command that !foo would run also add it to the command history
  • !$: Run the last word of the previous command (same as Alt + .)
  • !$:p: Print out the word that !$ would substitute
  • !*: Run the previous command except for the last word
  • !*:p: Print out the previous command except for the last word
  • ^foo^bar: Run the previous command replacing foo with bar
  • $!: process ID of the most recently executed background pipeline
  • $$: PID of the current shell

Arithmetic

COUNTER=0
$((COUNTER++))

Running a script downloaded with curl directly in the Bash shell

See the k3s sample example:

curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644

How to pass arguments along with a stdout-piped script

If the -s option is present, or if no arguments remain after option processing, then commands are read from the standard input. This option allows the positional parameters to be set when invoking an interactive shell.

curl http://foo.com/script.sh | bash -s arg1 arg2

How to get both stdout and the exit code

function print_checksum
{
    echo -n "TEST"
    return 1
}

function main1
{
    local actual
    actual=$(print_checksum)
    echo $?  # 1
}

function main2
{
    local actual=$(print_checksum)
    echo $?  # 0
}

Use it like the main1 function. Note that if you use local together with command substitution (Command Substitution; $()), the $? value is not received correctly. See SC2155 for related details.

Alternatively, you can pass a variable name to the function and use eval:

function myfunc()
{
    local  __resultvar=$1
    local  myresult='some value'
    eval $__resultvar="'$myresult'"
}

myfunc result
echo $result

Bash options

Options let you change the behavior of the shell or a script. The set command lets you turn on options inside a script. Where the option should apply, write set -o -option-name or simply set -option-abbrev. The two forms behave the same.

#!/bin/bash
# 모든 명령어는 실행전에 echo 됨.
set -o verbose

# 위와 완전히 똑같음.
set -v

To Disable an option you have enabled, use set +o option-name or set +option-abbrev.

For the list of available options, see the set part of bash(1) - Linux manual page # SHELL BUILTIN COMMANDS. (searching for allexport finds it right away)

The list of abbreviations is as follows:

Abbreviation

Name

Meaning

-C

noclobber

Prevents files from being overwritten by redirection (may be possible with >|)

-D

(none)

Only lists double-quoted strings preceded by $ and does not execute commands

-a

allexport

Exports all defined variables

-b

notify

Notifies when background jobs terminate (not used that often in scripts)

-c ...

(none)

Reads commands from ...

-f

noglob

Turns off filename expansion (globbing)

-i

interactive

Runs the script in interactive mode

-p

privileged

Runs the script as "suid" (be careful!)

-r

restricted

Runs the script in restricted mode (see Chapter 21)

-u

nounset

Prints an error message and forcibly exits when an undefined variable is used

-v

verbose

Prints each command to standard output before executing it

-x

xtrace

Similar to -v but expands the commands

-e

errexit

Aborts the script at the first error (a command that exits with a non-zero status)

-n

noexec

Only reads the script's commands without executing them (syntax check)

-s

stdin

Reads commands from standard input

-t

(none)

Exits right after the first command

-

(none)

End of option flags. All remaining arguments are treated as positional parameters.

--

(none)

Does not accept positional arguments. If arguments are given (-- arg1 arg2), the positional parameters are set to the arguments.

set -x -e

set -euo pipefail

Seems to be used a lot in production code

  • -e - exits the script immediately if any command fails (exit code ≠ 0)
  • -u - exits with an error when an undefined variable is referenced
  • -o pipefail - treats the whole pipeline as failed if any stage fails
    • Without -o pipefail, in cmd1 | cmd2, even if cmd1 fails, only the exit code of cmd2 is checked and it is treated as success. With pipefail on, the exit code of the last failing command in the pipeline becomes the overall result.

set -a ... set +a

set -a
source ".env"
set +a

The export command in bash

Why you can never make an already running script behave as if it had been run with source:

이미 실행된 스크립트에서 source 로 실행한것처럼 하는건 절대 안됩니다.
반드시 source test.sh 또는 . test.sh (. 명령)을 써야 합니다.
그 이유는 현재 쉘이 어떤 명령을 실행할때 source나. 명령이 아닌경우 (예를 들면 $ ls ) 현재 쉘이 CHILD 를 포크해서 execlp 로 ls 명령을 실행하고 원래의 쉘은 SIGCLD 가 올때까지,
즉 자식( ls) 이 죽을때 까지 pause() 하고 있기 때문에 원래 쉘로 돌아왔을때는 자식이 export 한것은 전혀 소용 없게 됩니다.
export 는 putenv() 함수를 이용하여 특정문자열("변수명=변수값") 을 환경영역에 옮기는 명령이고 이건 CHILD 들에게만 영향을 미치기 때문입니다.

How to read a .env file and Export all variables

set -o allexport
source .env
set +o allexport

Searching Command History in the Bash shell

Add the following to inputrc:

"\e[A":history-search-backward
"\e[B":history-search-forward

See GNU Readline for details.

Writing tab completion

  • Writing simple tab completion for Bash and Zsh | GeekNews
  • Introduces how to implement tab completion in Bash and Zsh that shows descriptions even for already completed words
  • Bash and Zsh use different tab completion APIs, and only Zsh shows descriptions in completions by default
  • Implements a structure where _generate_foo_completions generates the candidates, returned via COMPREPLY in Bash and compadd in Zsh
  • To bring Zsh's description feature to Bash, descriptions are included in the candidate strings and removed only when there is a single candidate
  • Improved so that ambiguity is intentionally added even for a single candidate, so descriptions appear on <TAB>
  • The final script provides the same user experience in both shells and supports partial completion, full completion, and candidate descriptions

< vs << vs <<<

Command

Name

Description

Example

<<<

Here String

Passes a string as standard input

wc -w <<< "Hello, world!"

<<

Here Document

Passes a multi-line string as standard input

cat << EOF ... EOF

<

Input Redirection

Passes a file as standard input

wc -w < filename.txt

As an easy example of <<<, the following two commands are equivalent:

  • echo "Hello, World!" | wc -w
  • wc -w <<< "Hello, world!"

[ vs [[ vs ( vs ((

(…)

Denotes a subshell.

With a leading dollar sign, as in $(…), it is command substitution]:

There is a command inside the parentheses, and the command's output is used as part of the command line. 3

{…}

Braces are like parentheses in that they group commands, but they only affect parsing, not grouping.

  • x=2; { x=4; }; echo $x prints 4.
  • x=2; (x=4); echo $x prints 2.

Also braces being keywords need to be delimited and found in command position (hence the space after { and the ; before }) whereas parentheses don't. That's just a syntax quirk.

((…))

Double parentheses enclose an arithmetic command, a calculation on integers using syntax similar to other programming languages.

This syntax is mainly used for assignments and conditionals.

It exists only in ksh/bash/zsh, not in plain sh.

The same syntax is used in arithmetic expressions, $((…)), which expand to the integer value of the expression.

[…]

  • [ is a POSIX executable file.
  • [ is just an executable. And ] is simply the last argument of [.
  • Ubuntu 16.04 actually has an executable at /usr/bin/[ provided by coreutils, but the bash built-in Command takes precedence.

single brackets surround conditional expressions. Conditional expressions are mostly built on operators such as -n "\(variable" to test if a variable is empty and -e "\)file" to test if a file exists. Note that you need a space around each operator (e.g. [ "\(x" = "\)y" ], not [ "\(x"="\)y" ]), and a space or a character like ; both inside and outside the brackets (e.g. [ -n "\(foo" ], not [-n "\)foo"]).

…

  • <code> is a [[Korn shell-inspired Bash extension

double brackets are an alternate form of conditional expressions in ksh/bash/zsh with a few additional features, for example you can write -L $file && -f \(file</span> to test if a file is a symbolic link to a regular file whereas single brackets require [ -L "\)file" ] && [ -f "$file" ]. See Why does parameter expansion with spaces without quotes works inside double brackets but not single brackets [? for more on this topic. === Addition: =~ comparison operator == * [[ ab =~ ab?</code> is a POSIX extended regular expression match. ? is not expanded as a glob.

  • [ a =~ a ] is a syntax error. It does not apply to bash.

So which one should I use?

If you need POSIX extensions, use [, ].

$* vs $@

See [tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html Bash Guide for Beginners] for details. They do almost the same thing, differing in how they split, but their behavior changes when double quotes are used.

$*
Expands to the positional parameters, starting from one.
When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable.
  • For example, to join strings with a separator, use something like joined=$(IFS=,; echo "${src_paths[*]}").
$@
Expands to the positional parameters, starting from one.
When the expansion occurs within double quotes, each parameter expands to a separate word.

Double-quote expansion works the same way when using arrays. Therefore it is safer to use "${filelist[@]}" instead of #{filelist[*]}.

Example

# test.sh file
IFS='||'
echo "$*"

Running bash test.sh a b c d outputs a|b|c|d.

# test.sh file
IFS='||'  # $@ 를 사용할 경우 작동에 아무런 영향을 끼치지 않는다.
echo "$@"

Running bash test.sh a b c d outputs a b c d.

:>

:> is a bash command that empties (truncates) a file.

How it works:

  • : is a built-in command that does nothing (no-op)
  • > is the redirection operator

Combined, they delete the file's contents and make it 0 bytes.

# 로그 파일 비우기
:> /var/log/application.log

Comments

For comments in multi-line commands, use the form &#96;#...&#96;:

command ... \
  -e FIREFOX_CLI=https://.../ `#optional` \
  ...

Various which methods

Use the following commands.

Of these, the POSIX-compatible method is command:

command -v <the_command>

How to check whether PIPE input was passed

check if file descriptor of stdin (0) is open or closed:

[ ! -t 0 ] && echo "stdin has data" || echo "stdin is empty"

Then, if you want to put the PIPE stdin result into a variable:

read -r -u 0 INPUT_VALUE

Script debugging

set -o option

Command-line option

Behavior

noexec

-n

Checks only for syntax errors without executing commands. Ignored in interactive scripts.

verbose

-v

Prints commands to the screen before executing them.

xtrace

-x

Prints commands to the screen after processing the command line.

noglob

-f

Does not expand pathnames. (No filename expansion using metacharacters, i.e., special characters such as * cannot be used)

  • set -e: Exit immediately if a command exits with a non-zero status.

Using timeout in Bash scripts

Troubleshooting

A summary of problems that occur while using Bash.

Error passing arguments with spaces between scripts

See the #$* vs $@ section.

CVE-2014-6271

/bin/sh^M: bad interpreter: No such file or directory

Running the script produces the following error.

-bash: ~: /bin/sh^M: bad interpreter: No such file or directory

This problem is almost certainly caused by Windows line endings (CRLF). Run vi -b to edit in binary mode and delete the ^M characters.

Not found "[["

If your script is executable and you are executing it like ./getconfig.sh, the first line of your script needs to be:

#!/bin/bash

If you wrote #!/bin/sh, you need to fix it.

FOR COMMAND: file loop warning

When using for to LOOP over a list of files, be careful: using quoting in the filter between in and do will not work properly.

## Warning: Don't use the quoting("...").
for cursor in $INSTALL_DIR/*.sh; do
    echo $cursor
done

HOME key malfunction when setting PS1

When setting PS1 with a \$ right before the input cursor, it is best not to add Escape strings such as colors after the \$. Using the HOME key may cause character counting errors.

warning: setlocale: LC_ALL: cannot change locale

See setlocale#warning: setlocale: LC_ALL: cannot change locale.

Unicode characters like ë suddenly being entered

See Terminal emulator#How to enter Unicode characters in Linux.

Unicode characters like e̲ suddenly being entered

See Emoji#Emoji insertion mode.

See also

Favorite site

Basic

Tutorials

Tips

  • [Recommended] Minimal safe Bash script template - introduces a small, safe template for Bash scripts, which, unlike other programming languages, you forget the moment you look away.

References


  1. Bash & (Ampersand) ↩

  2. Stackoverflow: \curl … | bash … what's the slash for? ↩

  3. About the case inside double quotes ↩

  4. Insfords_jspwiki_shell_script.pdf ↩

  5. Cygwin_bash-korean_setting.pdf ↩

  6. Adv-bash-scr-howto.zip ↩

  7. BASH_shell-script.pdf ↩

author Zer0 sitemap