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 합니다.

declare -i idx 로 idx 변수에 integer 속성을 주더라도 idx++ 와 같은 문법은 사용할 수 없습니다. 왜냐하면 쉘 에서는 idx++ 가 명령 이름이 되기 때문입니다. 대신에 idx+=1 와 같은 대입 연산에서는 integer 속성이 적용될 수 있습니다.

declare -i idx=0
idx++              # 오류!  여기서 idx++ 는 명령 이름이 된다.
idx+=1             # ok

# let 을 사용하면 declare 가 필요없다.
idx=0
let idx++          # ok

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
}