Bourne Shell Builtins

.

. filename [arguments]

bash 에서 source 명령과 같은 기능의 명령입니다. sh 에서는 source 명령을 사용하지 못하므로 이 명령을 사용해야 합니다. filename 을 읽어들여 현재 shell 에서 실행하는데 가령 AA.sh 파일내용 중에 . BB.sh 라인이 있다면 해당라인이 위치한 곳에 BB.sh 파일을 읽어들여 실행합니다. child process 가 생성되는 것은 아니고 현재 AA.sh process 에서 실행됩니다.

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

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

:

:

아무일도 하지 않는 명령입니다. 종료 상태 값으로 항상 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 인자를 사용할수 있습니다.

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 ...]

  • 현재 shell process 를 command 로 대체합니다. 프롬프트 상에서와 달리 스크립트 실행시에는 command 를 실행할수 없을경우 exit 됩니다. ( exit 을 방지하기 위해 execfail 옵션을 사용할수 있습니다. )

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

exit

exit [n]

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

export

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

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

A.sh 에서 export 한 변수를 B.sh 에서 읽고 수정하고 할 수 있지만 변경된 사항이 parent process 인 A.sh 에 적용되지는 않습니다.

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

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

getopts

getopts optstring name [arg]

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

hash

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

현재까지 사용된 명령들의 위치와 사용횟수를 기억하고 관리할수 있습니다.

pwd

pwd [-LP]

현재 사용중인 디렉토리를 표시합니다. $PWD 값과 같으며 -P 옵션을 사용할경우 심볼릭 링크 디렉토리 구조를 따르지 않고 물리적 디렉토리 구조를 따라 표시합니다.

readonly

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

변수나 함수를 변경할수 없게 합니다. 설정후 변경을 시도하면 오류메시지와 1 을 리턴합니다.

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 에는 $ 를 붙이지 않습니다.

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 에 사용할수 있습니다.

#!/bin/bash

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

f1() { die "*** an error occured ***"; }
f2() { f1; }
f3() { f2; }

f3

################ output #################

12 f1 ./callertest.sh
13 f2 ./callertest.sh
14 f3 ./callertest.sh
16 main ./callertest.sh
*** an error occured ***

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 으로 등록되어 사용 중인 명령 자동완성 에대해서 옵션을 변경할 수 있습니다.

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 함수 이름만 표시합니다.
(디버깅 시에는 line number 와 source file 도 표시합니다.)
-g 함수 내에서 declare 는 기본적으로 local 변수를 만듭니다.
하지만 이 옵션을 사용하면 global 변수가 됩니다.
-p NAME 의 속성과 값을 볼때 사용합니다.

속성을 줄때 사용하는 옵션

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

옵션 설명
-a NAME 에 indexed arrays 속성을 줍니다.
-A NAME 에 associative arrays 속성을 줍니다.
-i NAME 에 integer 속성을 줍니다.
값을 대입할때 let 명령과 같이 산술연산을 할 수 있습니다.
-n NAME 에 named reference 속성을 줍니다.
-r NAME 에 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 ...]

기본적으로 escape 문자는 처리하지 않으며 라인 마지막에 newline 을 붙이는데 필요하지 않을경우 -n 옵션을 사용할수 있습니다. -e 옵션을 사용하면 escape 문자가 처리됩니다.

enable

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

builtin 명령을 disable 또는 enable 시키는데 사용합니다. builtin 명령과 동일한 이름의 외부 명령을 사용하고자 할 때 이 명령으로 builtin 명령을 disable 시킬 수 있습니다.

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 expressions 메뉴를 참조하세요

local

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

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

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

    cnt=100
    echo $cnt

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

$ f1
100
101

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 array < datafile   # 이명령은 실질적으로 아래와 같습니다.

while read -r line 
do
    array[i]="$line"
    i=$((i + 1))
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 에서 디렉토리 항목을 삭제합니다.

[ 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 명령 만들기 ]

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 옵션을 사용해 값의 설정 여부를 테스트할 수 있습니다.

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

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

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

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 awk xxx
/usr/bin/awk

$ echo $?
1
  • -P 옵션은 name 이 외부 파일로 존재하는지 테스트할때 사용할 수 있습니다.
$ 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

이 옵션은 which 명령과 기능이 비슷한데 다른 점은 which 명령은 파일이 executable 인지도 체크합니다.

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

typeset

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

declare 명령과 같이 변수의 값이나 속성을 설정하는데 사용합니다. (Obsolete)

ulimit

ulimit [-SHabcdefilmnpqrstuvxT] [limit]

shell 의 리소스 제한을 설정합니다. hard limit (-H) 은 root 유저만 설정할수 있고 soft limit (-S) 은 hard limit 이내에서 일반유저가 설정할수 있습니다. 설정된 값은 해당 shell 과 생성되는 child process 에 적용됩니다. 웹서버나 데이터베이스 서버등을 운영할때 설정값이 너무 낮으면 열린 파일수가 너무 많다거나 스레드를 생성할수 없다거나 하는 리소스관련 오류가 발생할 수 있습니다. 이때는 startup script 파일에서 ulimit 명령을 이용하여 관련된 리소스를 설정하거나 또는 시스템 설정 파일을 수정하여 reboot 후에도 유지되게 합니다.

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

# 다음은 프로세스당 열수있는 최대 파일수를 설정하는 예입니다.

/etc/security/limits.conf 
파일에 추가

* soft nofile 65536
* hard nofile 65536
root soft nofile 65536
root hard nofile 65536

----------------------------------------

/etc/pam.d/common-session-noninteractive
/etc/pam.d/common-session
파일에 추가

session required pam_limits.so

unalias

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

설정된 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 명령을 사용할 수 있습니다.
# Author : petar marinov, http:/geocities.com/h2428

cd()
{
    local opt OPTIND
    local new_dir adir
    local cnt x2 index

    # 기존 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

    if [ "$1" = "--" ]; then
        dirs -v
        return
    fi

    new_dir=$1
    [ -z "$1" ] && new_dir=$HOME

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

    # 디렉토리 이름 앞에 '~' 문자가 있을 경우 $HOME 으로 대체
    [ "${new_dir:0:1}" = "~" ] && new_dir=$HOME${new_dir:1}

    # $new_dir 로 cd 하고 동시에 stack 의 top 에 항목을 add 합니다.
    pushd -- "$new_dir" > /dev/null
    [ $? -ne 0 ] && return 1
    new_dir=$(pwd)

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

    # 마지막으로 기존 history 를 검색해 현재 디렉토리와 중복되는 항목이 있으면 삭제합니다.
    for ((cnt=1; cnt <= 15; cnt++)); do
        x2=$(dirs +$cnt 2>/dev/null)
        [ $? -ne 0 ] && return
        [ "${x2:0:1}" = "~" ] && x2=$HOME${x2:1}
        if [ "$x2" = "$new_dir" ]; then
            popd -n +$cnt > /dev/null
            let cnt--
        fi
    done

    return 0
}

export -f cd