Bourne Shell Builtins

Shell 내부에 builtin 되어서 제공되는 명령들입니다. 외부에 파일로 존재하지 않으므로 sudo, env, 또는 find 의 -exec 등으로 실행할 수 없고 shell 환경에서만 사용할 수 있습니다.

.

. filename [arguments]

. ( dot ) 은 as 어셈블러나 ld 링커 스크립트에서 현재 위치를 나타내는데 사용됩니다. shell 에서는 현재 위치에 filename 내용을 include 하는데 사용됩니다. bash 에서는 동일한 기능의 source 명령을 추가로 제공합니다. 가령 AA.sh 파일 내용 중에 . BB.sh 라인이 있다면 해당 라인이 위치한 곳에 BB.sh 파일을 읽어들인 후 실행하는 것과 같습니다.

function 과 동일하게 arguments 를 줄 수 있으며 BB.sh 에서는 return 명령을 사용할 수 있습니다. 인수를 주지 않을 경우 AA.sh 실행시 사용된 인수가 동일하게 적용됩니다.

filename 에 경로를 지정하지 않으면 $PATH 를 검색하는데 찾지 못하면 오류메시지와 함께 non-zero 를 리턴합니다.

간혹 쉘 스크립트 파일을 프롬프트 상에서 .source 명령으로 실행시키는 경우가 있는데 옳은 방법이 아닙니다. 그렇게 되면 shebang 라인도 적용이 안되고 스크립트 파일 내의 모든 라인을 현재 프롬프트 shell 에서 실행하는 것과 같게 되는 것입니다.

$ cat AA.sh 
#!/bin/bash
echo AA.sh start...
. BB.sh                   # '.' 명령을 이용해 BB.sh 을 include 합니다.
echo AA.sh end...

$ cat BB.sh               # include 되는 BB.sh 은 shebang 라인이 필요없음.
echo BB.sh start...
echo args : $1 $2 $3
echo BB.sh end...

########## 실행결과 ############

$ ./AA.sh 
AA.sh start...
BB.sh start...
args :
BB.sh end...
AA.sh end...

$ ./AA.sh 11 22 33      # 11 22 33 인수 추가
AA.sh start...
BB.sh start...
args : 11 22 33         # AA.sh 에서 사용한 인수가 적용된다.
BB.sh end...
AA.sh end...

##### 다음은 AA.sh 에서 '.' 명령에 직접 인수를 추가
$ cat AA.sh 
#!/bin/bash
echo AA.sh start...
. BB.sh 44 55 66        # '.' 명령에 44 55 66 인수 추가
echo AA.sh end...

$ ./AA.sh 11 22 33
AA.sh start...
BB.sh start...
args : 44 55 66         # '.' 명령에 사용한 인수가 적용된다.
BB.sh end...
AA.sh end...

##### 다음은 include 되는 BB.sh 의 중간에 return 명령 추가
$ cat BB.sh 
echo BB.sh start...
return 3
echo args : $1 $2 $3
echo BB.sh end...

$ cat AA.sh 
#!/bin/bash
echo AA.sh start...
. BB.sh 44 55 66
echo $?                 # BB.sh 의 return 값을 조회할수 있다.
echo AA.sh end...

$ ./AA.sh 
AA.sh start...
BB.sh start...          # return 되어 BB.sh start... 만 표시된다.
3                       # BB.sh return 값
AA.sh end...

:

:

아무일도 하지 않는 명령입니다. 종료 상태 값으로 항상 0 을 리턴합니다. 실질적으로 true 명령과 동일합니다 ( 예전에는 true 명령이 이 명령의 alias 였습니다 ). 간단한 스크립트 테스트를 할 때 true 가 올수 있는 자리에 대신 사용하기에 편합니다. 또한 실행 시에 인수 부분에서 변수확장, 명령치환, 산술확장이 이루어지므로 디버깅 시에 특정 값을 보기 위해 사용할 수도 있습니다. 여러모로 활용성이 있는 명령입니다.

while :; do echo $(( i++ )); sleep 1; done

if :; then :; else :; fi

# dir 변수가 존재하지 않거나 null 값일 경우 '/usr/local' 을 대입
: ${dir:=/usr/local}

break

break [n]

for, while, until 반복문에서 사용되는 명령입니다. 현재 실행되고 있는 반복을 중단하는 역할을 합니다. 반복문이 중첩 될수있는데 이때 n 인자를 사용할수 있습니다.

반복문을 break 명령으로 종료했을 경우 종료 상태 값은 0 이됩니다.

cd

cd [-L|[-P [-e]] [-@]] [dir]

현재 작업중인 디렉토리를 변경합니다. -P 옵션을 주면 심볼릭 링크 디렉토리 구조를 따르지 않고 물리적 디렉토리 구조를 따름니다

continue

continue [n]

for, while, until 반복문에서 사용되는 명령입니다. continue 명령이 실행되면 현재 반복을 중단하고 다음 반복으로 넘어갑니다. 반복문이 중첩될 수 있는데 이때 n 인자를 사용할 수 있습니다.

eval

eval [arg ...]

eval 메뉴 참조.

exec

exec [-cl] [-a name] [command [arguments ...]] [redirection ...]

  • 프로그램 loader 라고도 하는데 현재 shell process 를 command 로 대체합니다. 그러니까 디스크에서 프로그램 이미지를 읽어와서 현재 shell process 가 차지하고 있는 메모리 주소공간을 대체하는것 입니다. 따라서 ps 목록에 보이는 이름도 바뀌게 됩니다. command 를 실행할수 없을경우 프롬프트 상에서와 달리 스크립트 실행시에는 exit 됩니다. ( exit 을 방지하기 위해서 execfail 옵션을 사용할수 있습니다. )

  • 현재 shell 에 redirection 을 적용시킵니다.

bash 전용 옵션

  • -a name : 0 번째 인수는 명령 자신의 이름을 나타내는데 이 옵션으로 변경할수 있습니다.
    ( /proc/$PID/cmdline 값과 관련된 것으로 ps 목록에도 변경된 이름이 나타납니다. )
  • -c : empty environment 상태로 명령을 실행합니다. ( env -i 와 같은 역할 )
  • -l : login shell 로 실행합니다. 명령이름 앞에 - 문자가 붙게됩니다.
$ ( exec -a testps ps -o pid,ppid,cmd ) 
  PID  PPID CMD
24889  3379 /bin/bash
28594 24889 testps -o pid,ppid,cmd          # "ps" 명령 이름이 "testps" 로 변경돼 출력

$ ( exec -l -a testps ps -o pid,ppid,cmd )
  PID  PPID CMD
24889  3379 /bin/bash
28611 24889 -testps -o pid,ppid,cmd         # testps 이름앞에 '-' 문자가 붙는다

$ ( exec sh -c 'echo $EDITOR' )
/usr/bin/vim
$ ( exec -c sh -c 'echo $EDITOR' )          # -c 옵션은 empty environment
$

exit

exit [n]

shell 을 exit 합니다. n 은 종료 상태 값이 되며 $? 를 통해 구할수 있습니다. n 값을 설정하지 않으면 이전 명령의 종료 상태 값이 사용됩니다.

export

export [-fn] [name[=value] ...] or export -p

A.sh 스크립트 내에서 B.sh 스크립트를 실행시키면 A.sh 은 parent, B.sh 은 child process 가 됩니다. 이때 A.sh 에서 설정한 변수, 함수들은 B.sh 에서 사용할 수가 없는데 export 명령을 이용하면 child process 인 B.sh 에서도 사용할 수가 있게 됩니다.

  • export 는 처음 한번만 해주면 됩니다.

  • 함수를 export 할 때는 -f 옵션을 사용합니다.

  • 명령 실행시 인수를 주지 않으면 export 된 값을 출력합니다.

  • sh 에서는 변수만 export 할 수 있고 function 은 export 할 수 없습니다.

getopts

getopts optstring name [arg]

명령행에서 사용되는 옵션들을 처리하기 위해 사용되는 명령입니다.

hash

hash [-lr] [-p pathname] [-dt] [name ...]

프롬프트 상에서 명령을 실행할 때 절대 경로를 사용하지 않으면 $PATH 환경 변수에 설정된 순서대로 디렉토리를 검색해서 명령을 찾습니다. 그리고 한번 찾은 명령은 다음에 재검색 없이 실행하기 위해서 hash 테이블에 저장해 놓는데요. hash 명령을 사용하면 $PATH 를 검색해서 찾은 명령들의 목록을 볼 수 있고 삭제할 수 있습니다.

기본적으로 $PATH 환경 변수를 재설정하면 자동으로 저장된 목록이 reset 됩니다.
sh 에서도 동일함 ( 예: PATH="$VIRTUAL_ENV/bin:$PATH" )

pwd

pwd [-LP]

현재 작업 중인 디렉토리를 출력하는 방법에는 $PWD 변수, pwd 빌트인 명령 그리고 pwd 외부 명령도 있는데 모두 결과는 같습니다. pwd 명령의 경우 -P 옵션을 사용하면 심볼릭 링크를 해석해서 physical 디렉토리를 출력해 줍니다. pwd 빌트인 명령의 경우는 -L 옵션이 디폴트고, pwd 외부 명령의 경우는 -P 옵션이 디폴트입니다.

# physical 절대경로를 구해 SDK_DIR 변수에 대입.
SDK_DIR=$( cd "${BIN_DIR}/.." && pwd -P )

readonly

readonly [-aAf] [name[=value] ...] or readonly -p

readonly 변수나 함수를 설정할 때 사용합니다. 설정 후 변경을 시도하면 오류메시지와 함께 종료 상태 값으로1 을 반환합니다. readonly 변수가 되면 unset 할 수도 없습니다.

sh 에서는 readonly 변수만 설정할 수 있습니다.

      -a        indexed array 변수
      -A        associative array 변수
      -f        shell functions
      -p        readonly 변수들을 출력 ( -f 를 추가하면 함수만 출력 )
----------------------------------------------------------------------

$ readonly AA=100                              $ BB=( [aa]=100 [bb]=200 )

$ AA=200                                       $ readonly -A BB
bash: AA: readonly variable                    
                                               $ BB+=( [cc]=300 )
$ echo $?                                      bash: BB: readonly variable
1                                              
                                               $ echo $?
$ unset -v AA                                  1
bash: unset: AA: cannot unset: readonly variable

$ echo $?
1

$ declare -p EUID UID PPID
declare -ir EUID="1000"        # readonly 변수는 "r" 이 추가된다.
declare -ir UID="1000"
declare -ir PPID="2515"

return

return [n]

function 또는 source 한 스트립트 에서 리턴합니다. n 값은 종료 상태 값으로 사용되어 $? 변수를 통해 얻을수 있습니다. return 명령을 사용하지 않을경우 마지막 실행명령의 종료 상태 값이 사용됩니다.

shift

shift [n]

positional parameters 메뉴 참조.

test

test [expr]

Test 메뉴 참조.

trap

trap [-lp] [[arg] signal_spec ...]

trap 메뉴 참조.

umask

umask [-p] [-S] [mode]

User file-creation mode mask 는 파일과 디렉토리를 생성할때 기본적으로 어떤 퍼미션으로 생성할지를 8진수값으로 설정합니다. mask 를 전혀주지 않는다면 ( 000 ) 기본적으로 파일은 666, 디렉토리는 777 로 생성됩니다. 마스크값을 022 로 준다면 파일은 666 에서 각자리수 별로 빼기계산을 하면 644 로 생성이 되고 디렉토리는 755 로 생성이 되게 됩니다. 좀더 자세한 내용은 여기 를 참고하세요.

unset

unset [-f] [-v] [-n] [name ...]

현재 설정돼있는 변수나 함수를 삭제하여 존재하지 않는 상태로 만듭니다. readonly 속성이 있을경우 unset 되지 않습니다. AA=, AA="", AA='' 는 값은 null 이지만 현재 존재하는 ( set 돼있는 ) 변수입니다. unset 을하면 존재하지 않는 상태가 됩니다. [ -v name ] 으로 테스트 해볼수 있습니다. 이때 name 에는 $ 를 붙이지 않습니다.

명령 실행시 옵션을 주지 않으면 첫번째로 변수를 unset 시도하고 실패할 경우 함수를 unset 시도합니다. 따라서 변수를 unset 할때는 항상 -v 옵션을 사용하는 것이 좋습니다.

  • -v name 을 변수로 취급합니다.
  • -f name 을 함수로 취급합니다.
  • -n name 을 reference 로 취급합니다.

Bash Builtins

[

[ arg... ]

test 명령과 동일한 명령입니다. Test 메뉴를 참조하세요.

alias

alias [-p] [name[=value] ... ]

alias 를 설정하는데 사용합니다. alias 는 기본적으로 non-interactive shell 에서는 사용할수 없습니다.

bg

bg [job_spec ...]

job control 메뉴 참조

bind

bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]

readline 의 설정 파일인 inputrc 에서 할수있는 옵션설정, key binding 을 이 명령을 통해서 동일하게 할 수 있습니다. 사용할 수 있는 함수나 옵션의 목록을 볼수도 있으며 현재 설정 상태도 확인할 수 있습니다.

builtin

builtin [shell-builtin [arg ...]]

우선순위가 높은 alias, function 이름을 피해 builtin 명령을 실행 할때 사용합니다.

caller

caller [expr]

현재 실행중인 함수의 call stack 을 표시합니다. 인수없이 사용하면 라인넘버, 파일이름 (${BASH_LINENO[0]} ${BASH_SOURCE[1]}) 을 표시하고 숫자를 인수로 주면 라인넘버, 호출함수, 파일이름 (${BASH_LINENO[$i]} ${FUNCNAME[$i+1]} ${BASH_SOURCE[$i+1]}) 을 표시합니다. stack trace 에 사용할수 있습니다.

$ cat ./caller.sh
#!/bin/bash

die() {
    echo "$1"
    local frame=0
    while caller $frame; do
        let frame++
    done
}

foo1() { die "*** an error occured ***" ;}
foo2() { foo1 ;}
foo3() { foo2 ;}

foo3
------------------------------------------

$ ./caller.sh 
*** an error occured ***
12 foo1 ./caller.sh
13 foo2 ./caller.sh
14 foo3 ./caller.sh
16 main ./caller.sh

command

command [-pVv] command [arg ...]

우선순위가 높은 alias, function 이름을 피해 외부명령을 (builtin 명령 포함) 실행 할때 사용합니다.

-v 옵션은 명령이 존재하는지 체크하는데 사용할 수 있습니다.

if command -v python > /dev/null; then ...

compgen

compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]

명령 자동완성에 사용될 단어들를 생성하는데 사용됩니다. 주로 자동완성 함수를 작성할때 COMPREPLY 배열에 값을 채워 넣기 위해 사용합니다. 사용 가능한 옵션은 complete 명령과 거의 동일하며 마지막에 word 인수가 주어지면 word 와 매칭되는 단어들만 선택됩니다.

# -A 옵션에 사용할 수 있는 action 들
$ compgen -A [tab]
alias      builtin    disabled   file       helptopic  keyword    setopt     stopped
arrayvar   command    enabled    function   hostname   running    shopt      user
binding    directory  export     group      job        service    signal     variable

$ compgen -a         # 현재 설정되어 있는 aliases 
$ compgen -b         # builtin commands
$ compgen -c         # $PATH 에의해 접근 가능한 시스템 전체 명령 (builtin 명령 포함)
$ compgen -d         # 현재 위치에서 디렉토리만 표시
$ compgen -e         # export 한 환경변수들
$ compgen -f         # 현재 위치에서 모든 파일 표시 (디렉토리, 심볼릭 링크 모두)
$ compgen -g         # /etc/group 에 등록된 group
$ compgen -j         # background 로 실행중인 모든 job 들
$ compgen -k         # shell keywords
$ compgen -s         # /etc/services 에 등록된 service
$ compgen -u         # /etc/passwd 에 등록된 user
$ compgen -v         # 현재 쉘에 설정되어 있는 모든 변수들 (export 안한것 포함)

complete

complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]

특정 이름의 자동완성을 등록하고 설정하는 역할을 합니다.
자세한 내용은 Command Completion 메뉴를 참조하세요

compopt

compopt [-o|+o option] [-DE] [name ...]

complete 으로 등록되어 사용 중인 명령 자동완성 에대해서 옵션을 변경할 수 있습니다. -o 은 on 을 나타내고, +o 는 off 를 나타냅니다. name 은 자동완성이 적용된 명령이름 입니다.

한가지 중요한 기능은 자동함수 내에서 name 없이 사용하면 현재 tab 실행에 대해서만 옵션을 적용시킬 수 있습니다.

# clang 명령의 자동완성에 대해서 nospace 옵션이 이후 지속적으로 적용된다.
compopt -o nospace clang

# 현재 실행중인 tab 실행에 대해서만 옵션이 적용된다.
compopt -o nospace

declare

declare [-aAfFgilnrtux] [-p] [name[=value] ...]

변수를 선언하고 속성을 적용합니다. 값을 대입하지 않으면 존재하지 않는 상태 (unset 상태) 로 남습니다. 변수, array 의 현재 속성과 값을 보거나 함수정의를 볼때도 사용합니다. 유효하지 않은 옵션을 사용하거나 값을 대입할때 오류가 나면 종료 상태 값으로 non-zero 를 리턴합니다.

sh 에서는 사용할 수 없습니다. 하지만 함수 내에서 local 은 사용할 수 있습니다.

  • Associative array 를 만들때는 declare -A 명령을 사용해야 합니다.
  • 함수 내에서 사용되면 기본적으로 local 변수로 설정됩니다.
    ( -g 옵션으로 global 변수로 설정할 수 있습니다. )
  • declare -n 을 이용하여 named reference 기능을 이용할 수 있습니다.
  • declare -t -f 함수명 을 사용하면 해당 함수에서 DEBUG, RETRUN trap 을 할 수 있습니다.

Options:

옵션 설명
-f 함수 정의를 볼때 사용합니다.
특정 action 을 함수에 적용시킬때 사용합니다.
-F 함수 이름만 표시합니다.
( shopt -s extdebug 디버깅 시에는 line number 와 source file 도 표시합니다 )
-g 함수 내에서 declare 는 기본적으로 local 변수를 만듭니다.
하지만 이 옵션을 사용하면 global 변수가 됩니다.
( 동일한 이름의 global 변수가 이미 존재하면 안됩니다.)
-p NAME 의 속성과 값을 볼때 사용합니다.

속성을 줄때 사용하는 옵션

- 대신에 + 를 사용하면 해당 속성이 off 됩니다.

옵션 설명
-a NAME 에 indexed arrays 속성을 줍니다.
-A NAME 에 associative arrays 속성을 줍니다.
-i NAME 에 integer 속성을 줍니다.
( 값을 대입할때 let 명령과 같이 산술연산을 할 수 있습니다. )
-n NAME 에 named reference 속성을 줍니다.
-r NAME 에 readonly 속성을 줍니다.
( 한번 readonly 속성이 되면 변경할 수 없습니다. )
-t NAME 에 trace 속성을 줍니다. 함수에만 적용되는 옵션입니다.
-l NAME 에 값을 대입할때 소문자로 변환합니다.
-u NAME 에 값을 대입할때 대문자로 변환합니다.
-x NAME 을 export 합니다.

dirs

dirs [-clpv] [+N] [-N]

pushd, popd 명령과 함께 directory stack 을 다루는데 사용되는 명령으로 현재 stack 내용을 보여줍니다. 0 번은 항상 현재 디렉토리를 나타냅니다.

[ pushd, popd, dirs 로 cd 명령 만들기 ]

disown

disown [-h] [-ar] [jobspec ...]

job control 메뉴 참조

echo

echo [-neE] [arg ...]

주어진 인수들을 출력합니다. quotes 을 사용하지 않을 경우 whitespace ( space, tab, newline ) 문자들은 single space 로 변경되어 출력됩니다. 기본적으로 escape 문자는 처리하지 않으며 라인 마지막에 newline 을 붙이는데 필요하지 않을경우 -n 옵션을 사용할수 있습니다. -e 옵션을 사용하면 escape 문자가 처리됩니다.

  • -n : 출력시 기본적으로 마지막에 newline 이 붙는데 이 옵션을 사용하면 붙이지 않습니다.
  • -e : escape 문자 처리를 enable 합니다.
  • -E : escape 문자 처리를 disable 합니다.

sh 의 경우 echo 명령은 bash 의 echo -e 와 동일하게 동작합니다.

enable

enable [-a] [-dnps] [-f filename] [name ...]

builtin 명령을 enable 또는 disable 시키는데 사용합니다. 기본적으로 제공되는 builtin 명령 외에 bash-builtins 패키지를 설치하면 추가적으로 명령을 builtin 으로 사용할 수 있습니다. builtin 명령과 동일한 이름의 외부 명령이 있을경우 builtin 명령을 disable 시키면 외부 명령이 사용됩니다.

$ enable      # 현재 enable 되어있는 builtin 명령을 볼 수 있습니다.
enable .      # disable 되어 있는 명령도 함께보려면 '-a' 옵션을 사용합니다.
enable :
enable [
enable alias
enable bg
. . . 
. . .
$ type -a echo
echo is a shell builtin
echo is /bin/echo

$ enable -n echo         # echo builtin 명령을 disable 시킵니다.

$ type -a echo
echo is /bin/echo

$ enable echo            # 다시 echo 명령을 enable 시킵니다.

$ enable | grep echo
enable echo

다음은 bash-builtins 패키지를 설치하여 sleep 명령을 builtin 으로 사용하는 예입니다. builtin 명령은 사용자가 직접 제작하여 사용할 수도 있는데 dpkg -L bash-builtins 출력에서 예제 소스를 볼 수 있습니다.

  • -f Load builtin NAME from shared object FILENAME
  • -d Remove a builtin loaded with -f
$ sudo apt install bash-builtins

# 사용할수 있는 명령의 목록을 볼 수 있습니다.
$ ls -l /usr/lib/bash/

# /usr/lib/bash/sleep 파일을 로드하여 builtin 으로 enable 시킵니다.
$ enable -f /usr/lib/bash/sleep sleep

$ type -a sleep
sleep is a shell builtin
sleep is /bin/sleep

$ enable -d sleep        # '-f' 옵션으로 로드한 파일을 remove 합니다.

false

false

항상 종료 상태 값 1 을 리턴하는 명령입니다.
명령이므로 실행이 돼야 종료 값을 얻을 수 있습니다.

$ echo false
false
$ false
$ echo $?
1

fc

fc [-e ename] [-lnr] [first] [last]

command history 에서 지정한 범위의 명령들을 에디터로 불러와 수정하여 스크립트 처럼 한번에 실행시킬수 있습니다.

fc -s [pat=rep] [command]

! 을 이용한 history 확장처럼 명령을 검색하여 실행할수 있습니다.

$ printf "%s\n" "hello\tworld"
hello\tworld

$ fc -s %s=%b printf
printf "%b\n" "hello\tworld"
hello    world

fg

fg [job_spec]

job control 메뉴 참조

help

help [-dms] [pattern ...]

Shell builtin 명령의 도움말을 보여줍니다.

history

history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]

command history 메뉴 참조.

jobs

jobs [-lnprs] [jobspec ...] or jobs -x command [args]

job control 메뉴 참조

kill

kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]

kill 메뉴 참조.

let

let arg [arg ...]

산술연산 표현식을 위한 명령입니다. 식을 작성할땐 기본적으로 공백없이 붙여야 합니다. 그러나 quote 를 할경우는 공백을 사용할 수 있습니다. 좀 더 자세한 내용은 special commands 메뉴를 참조하세요

local

local [option] name[=value] ...

local 변수를 설정할때 사용합니다. 그러므로 함수 내에서만 사용할 수 있습니다.
declare 명령에서 사용하는 옵션들을 동일하게 사용할 수 있습니다.

예를 들어 bash 에서 += 연산자는 기본적으로 스트링으로 처리하므로 숫자라도 concatenation 이 됩니다.

$ cnt=100

$ cnt+=20

$ echo $cnt    # 숫자가 스트링으로 처리되어 concatenation 된다.
10020

이때 -i 옵션을 이용해 integer 속성을 설정하면 산술연산을 할 수 있습니다.

$ f1() {
    local -i cnt=100      # cnt 변수의 속성을 integer 로 설정
    echo $cnt

    cnt+=20               # integer 속성을 가지고 있으므로
    echo $cnt             # cnt=$(( cnt + 20 )) 로 하지 않아도 된다.
}

$ f1
100
120

변수 선언을 먼저 하고 대입 연산은 뒤에 할 수 있습니다.

$ f1() {
    local AA    # 먼저 변수를 local 로 선언

    AA=100
    BB=200
}

$ f1; echo AA : $AA; echo BB : $BB
AA :
BB : 200

logout

logout [n]

login shell 일 경우에 logout 합니다. login shell 이 아니면 오류가 발생합니다.

mapfile

mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]

라인을 array 변수로 읽어들입니다. 변수명을 주지 않으면 MAPFILE 이 사용됩니다. 몇번째 라인부터 얼마나 읽어들일지, 저장되는 array 에는 몇번째 index 부터 입력할지 정할수 있고 callback 함수를 설정할 수도 있습니다.

mapfile -t arr < datafile   # 이명령은 실질적으로 아래와 같습니다.

while read -r line 
do
    arr[i++]=$line
done < datafile
  • -t
    읽어들이는 라인에서 newline 을 제거합니다.

  • -s count
    몇번째 라인부터 읽어들일지 지정합니다.

  • -n count
    몇개의 라인을 읽어들일지 지정합니다. 0 이면 전체 라인을 읽어들입니다.

  • -O origin
    array 변수에 몇번째 index 부터 입력할지 지정합니다.

  • -u fd
    file descriptor 로부터 라인을 읽어들입니다.

입력되는 array 와 별개로 callback 명령을 사용할 수 있습니다.

  • -C callback
    callback 명령을 지정합니다.

  • -c quantum
    몇개의 라인을 읽어들인후 callback 을 호출할지 지정합니다.

$ cat datafile
100  Emma    Thomas
200  Alex    Jason
300  Madison Randy
400  Sanjay  Gupta
500  Nisha   Singh

# callback 명령의  $1 에는 index 값이, $2 에는 라인이 전달됩니다.
$ f1() { echo "$1 : $2" ;}

$ mapfile -t -C f1 -c 1 < datafile      # -c 1 설정
0 : 100  Emma    Thomas
1 : 200  Alex    Jason
2 : 300  Madison Randy
3 : 400  Sanjay  Gupta
4 : 500  Nisha   Singh

$ mapfile -t -C f1 -c 2 < datafile      # -c 2 설정
1 : 200  Alex    Jason
3 : 400  Sanjay  Gupta

$ mapfile -t -C f1 -c 3 < datafile      # -c 3 설정
2 : 300  Madison Randy

callback 에서 read 명령을 사용하면 array 에 입력되는 라인이 skip 됩니다.

$ f1() { read -r line ;}

$ mapfile -t -C f1 -c 1 arr < datafile

# 200, 400 라인이 skip 되었다.
$ echo "${arr[0]}"
100 Emma Thomas
$ echo "${arr[1]}"
300 Madison Randy
$ echo "${arr[2]}"
500 Nisha Singh

popd

popd [-n] [+N | -N]

pushd, dirs 명령과 함께 directory stack 을 다루는데 사용되는 명령으로 stack 에서 디렉토리 항목을 삭제하고 cd 합니다.

[ pushd, popd, dirs 로 cd 명령 만들기 ]

printf

printf [-v var] format [arguments]

printf 메뉴 참조

pushd

pushd [-n] [+N | -N | dir]

popd, dirs 명령과 함께 directory stack 을 다루는데 사용되는 명령으로 인수로 사용된 디렉토리를 stack 에 추가하고 cd 합니다.

[ pushd, popd, dirs 로 cd 명령 만들기 ]

mug896@EliteBook:~$ dirs 
~
mug896@EliteBook:~$ pushd /usr                       # pushd 를 하면 현재 디렉토리가 
/usr ~                                               # 변경되면서 stack 에 추가된다.
mug896@EliteBook:/usr$ pushd /usr/local
/usr/local /usr ~
mug896@EliteBook:/usr/local$ pushd /usr/local/bin
/usr/local/bin /usr/local /usr ~
mug896@EliteBook:/usr/local/bin$ dirs -v -l
 0  /usr/local/bin
 1  /usr/local
 2  /usr
 3  ~
mug896@EliteBook:/usr/local/bin$ popd                # popd 를 하면 현재 디렉토리가
/usr/local /usr ~                                    # 변경되면서 stack 에서 삭제된다.
mug896@EliteBook:/usr/local$ popd
/usr ~
mug896@EliteBook:/usr$ popd
~
mug896@EliteBook:~$

read

read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]

read 메뉴 참조.

readarray

readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]

mapfile 명령과 동일합니다.

set

set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]

Shell option 을 설정하거나 명령의 인수값을 나타내는 $1 $2 $3 ... 변수를 설정하는데 사용합니다. enable 된 옵션은 $SHELLOPTS 변수에 : 로 분리되어 저장되며 $- 변수에는 옵션 flags 가 저장됩니다. 주의할점은 enable 시에는 - 기호를 disable 시에는 + 기호를 사용한다는 것입니다. [ -o 옵션명 ] 으로 현재 설정값을 테스트해볼 수 있습니다.

shopt

shopt [-pqsu] [-o] [optname ...]

Bash option 을 설정하는데 사용합니다. enable 된 옵션은 $BASHOPTS 변수에 : 로 분리되어 저장됩니다. enable 시에는 -s 를 disable 시에는 -u 옵션을 사용하고 -q 옵션을 사용해 값의 설정 여부를 테스트할 수 있습니다.

  • -o : 이 옵션은 set -o 옵션 값을 출력하는데 사용됩니다.

  • -p : 현재 옵션 상태를 출력하는데 결과를 바로 쉘에서 명령으로 사용할 수 있습니다.

  • -q : 아무런 출력을 하지 않게 합니다.

  • -s : 옵션을 enable 합니다.

  • -u : 옵션을 disable 합니다.

$ shopt -s nullglob
$ shopt -q nullglob; echo $?
0

$ shopt -u nullglob
$ shopt -q nullglob; echo $?
1
-------------------------------

# 1. noglob 은 set 옵션이므로 -o 옵션을 사용.
# 2. -p 옵션은 현재 옵션 상태를 출력합니다.
$ shopt -po noglob
set +o noglob

# 따라서 다음과 같이 현재 옵션을 백업하고 복구하는데 사용할 수 있습니다.
reset=$(shopt -po noglob)
set -o noglob 
. . .
$reset

source

source filename [arguments]

. (a period) 명령과 동일합니다.

bash 에서만 사용할수 있고 filename 을 찾을때 $PATH 에서 찾지 못하면 현재 디렉토리 에서도 찾습니다.

$ source <( echo 'AA=100; f1() { echo $AA ;}' )
$ f1
100
$ echo $AA
100
.................................................

# 인수로 11 22 를 전달하면 각각 $1, $2 에 할당됩니다.
$ source <( echo 'echo "XX, $1, $2, ZZ"' ) 11 22
XX, 11, 22, ZZ

suspend

suspend [-f]

job control 메뉴 참조

true

true

항상 종료 상태 값 0 을 리턴하는 명령입니다.
명령이므로 실행이 돼야 종료 값을 얻을 수 있습니다.

$ echo true
true
$ true
$ echo $?
0

times

Display process times.

Prints the accumulated user and system times for the shell and all of its child processes.

type

type [-afptP] name [name ...]

  • -a 옵션과 함께 사용할경우 alias, keyword, function, builtin, 외부 명령을 모두 구분해서 보여줍니다.

  • -f 검색에서 shell function 은 제외합니다.

  • -p 옵션은 name 이 실행 가능한지 테스트할 때 사용할 수 있습니다. 여기에는 alias, keyword, function, builtin, 외부 명령 모두 포함됩니다. 외부 명령의 경우에는 파일만 존재하면 참이 됩니다. ( executable 은 체크하지 않습니다 )

# time 은 keyword, ls 는 alias, cd 는 function, history 는 builtin, awk 는 외부 명령
$ type -p time ls cd history awk
/usr/bin/awk

$ echo $?
0

# xxx 가 존재하지 않는다.
$ type -p time ls cd history xxx awk
/usr/bin/awk

$ echo $?
1
  • -P 옵션은 name 이 외부 파일로 존재하는지 테스트할 때 사용할 수 있습니다. 이 옵션은 which 명령과 비슷한데 다른 점은 which 명령은 파일이 executable 인지도 체크합니다.
$ type -P ls date sed
/bin/ls
/bin/date
/bin/sed

$ echo $?
0

# 이번 경우는 history 가 builtin 명령이라 외부 파일로 존재하지 않는다.
$ type -P ls date history
/bin/ls
/bin/date

$ echo $?
1
  • -t name 의 타입을 표시합니다 ( alias, keyword, function, builtin, file ). 중복되어 존재할 경우 처음 하나만 표시됩니다.

typeset

typeset [-aAfFgilrtux] [-p] name[=value]

A synonym for declare (Obsolete)

ulimit

ulimit [-SHabcdefilmnpqrstuvxT] [limit]

shell 의 리소스 제한을 설정합니다. hard limit (-H) 은 root 유저만 설정할 수 있고 soft limit (-S) 은 hard limit 이내에서 일반 유저가 설정할 수 있습니다. 설정된 값은 child process 에게도 상속됩니다. 한 가지 터미널에서 설정할 때는 따로 옵션을 주지 않으면 hard limit 설정이 됩니다. 일반 유저는 한번 hard limit 을 내리면 다시 올릴 수 없으므로 -S 옵션을 사용해 설정해야 합니다.

웹서버나 데이터베이스 서버 등을 운영할 때 설정값이 너무 낮으면 열린 파일 수가 너무 많다거나 스레드를 생성할 수 없다는 리소스 관련 오류가 발생할 수 있습니다. 이때는 startup 스크립트 파일에서 ulimit 명령을 이용하여 관련된 리소스를 설정하거나 또는 시스템 설정 파일을 수정하여 reboot 후에도 유지되게 합니다.

현재 실행중인 프로세스의 설정 상태는 pid 를 구한후에 cat /proc/$pid/limits 명령으로 알아볼 수 있습니다.

# 다음은 프로세스당 열수있는 최대 파일수를 설정하는 예입니다.
# limits.conf 파일 설정은 pam_limits.so 모듈에 의해 처리됩니다.
# "*" 는 모든 유저를 뜻하고 nofile 은 (number of open files )

$ cat /etc/security/limits.conf
. . .
*      soft    nofile  65535
*      hard    nofile  65535
root   soft    nofile  65535        # "*" 는 root 에게는 적용이 안되므로
root   hard    nofile  65535

$ cat /etc/pam.d/login
. . .
session     required    pam_limits.so

다음은 recursion 을 이용해 현재 stack limit 을 확인하는 것입니다.

int 자료형은 보통 4 bytes 이므로 arr[100000]400000 bytes 만큼 stack 을 차지하게 됩니다.

$ ulimit -s                                  $ ulimit -S -s 4096
8192                                         $ ulimit -s
                                             4096

$ gcc -xc - <<\EOF && ./a.out                $ gcc -xc - <<\EOF && ./a.out
#include <stdio.h>                           #include <stdio.h>
int i = 0;                                   int i = 0;
void sub()                                   void sub()
{                                            {
    int arr[100000]; i++;                        int arr[100000]; i++;
    printf ("recursion %d : %d\n", \             printf ("recursion %d : %d\n", \
            i, i * 400000);                              i, i * 400000);
    sub();                                       sub();
}                                            }
int main() { sub(); }                        int main() { sub(); }
EOF                                          EOF
. . .                                        . . .
. . .                                        . . .
recursion 16 : 6400000                       recursion 6 : 2400000
recursion 17 : 6800000                       recursion 7 : 2800000
recursion 18 : 7200000                       recursion 8 : 3200000
recursion 19 : 7600000                       recursion 9 : 3600000
recursion 20 : 8000000    # 8M               recursion 10 : 4000000     # 4M
Segmentation fault (core dumped)             Segmentation fault (core dumped)

gcc 의 -fsplit-stack 옵션 을 사용하면 stack 을 제한없이 사용할 수 있습니다.

unalias

unalias [-a] name [name ...]

설정된 alias 를 삭제 하는데 사용합니다.

  • -a : 현재 설정되어 있는 전체 alias 를 삭제합니다.

wait

wait [-n] [id ...]

job control 메뉴 참조


pushd, popd, dirs 로 cd 명령 만들기

다음은 pushd, popd, dirs 명령을 이용하여 기존 cd 명령을 확장하는 예입니다.
기존 cd 명령은 history 기능이 없는데 pushd, popd 명령을 이용하여 history 기능을 구현합니다.
cd -- 로 history 목록을 볼 수 있고 cd -숫자 로 해당 디렉토리로 이동할 수 있습니다.
cd - 는 기존 명령과 동일하게 바로 이전 디렉토리로 이동합니다.

# 아래 내용을 cd.sh 파일에 저장 후 `source cd.sh` 하면 새로운 cd 명령을 사용할 수 있습니다.

function cd()
{
    local new_dir index dir cnt

    # 기존 builtin cd 명령의 옵션을 사용할 경우 처리를 위한 코드
    if ! [ $# -eq 0 ]; then
        if [[ $# -eq 2 && $1 == "--" ]]; then
            shift
        else 
            if ! { [ $# -eq 1 ] && [[ $1 =~ ^(-[0-9]{,2}|-|--|[^-].*)$ ]] ;}
            then
                builtin cd "$@"
                return
            fi
        fi
    fi

    [ "$1" = "--" ] && { dirs -v;  return ;}

    new_dir=${1:-$HOME}

    # 인수가 '-숫자' or '-' 형태일 경우
    if [[ "$new_dir" =~ ^-[0-9]{,2}$ ]]; then
        index=${new_dir:1}
        if [ -z "$index" ]; then
            new_dir=$OLDPWD
        else
            new_dir=$(dirs -l +$index) || return
        fi
    fi

    # $new_dir 로 cd 하고 동시에 stack 의 top 에 항목을 add 합니다.
    pushd -- "$new_dir" > /dev/null || return

    # 15 개의 history 만 사용할 것이므로 16번째 항목이 생길경우 stack 에서 삭제합니다.
    popd -n +16 &> /dev/null || true

    # 마지막으로 기존 history 를 검색해서 현재 디렉토리와 중복되는 항목이 있으면 삭제합니다.
    new_dir=$PWD cnt=1
    while dir=$(dirs -l +$cnt 2> /dev/null); do
        if [ "$dir" = "$new_dir" ]; then
            popd -n +$cnt > /dev/null
            continue
        fi
        let ++cnt
    done
}