# 셸의 콜론은 아무것도 하지 않는다. 그래도 사용하라

> Clean Markdown view of GeekNews topic #31814. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=31814](https://news.hada.io/topic?id=31814)
- GeekNews Markdown: [https://news.hada.io/topic/31814.md](https://news.hada.io/topic/31814.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-07-26T09:02:34+09:00
- Updated: 2026-07-26T09:02:34+09:00
- Original source: [refp.se](https://refp.se/articles/your-shell-and-the-magic-colon)
- Points: 1
- Comments: 1

## Topic Body

- 셸의 `:`는 아무 동작 없이 인수만 평가해 버리는 **널 명령(null command)** 으로, 매개변수 확장과 결합하면 필수 인수 검사와 기본값 설정을 간결하게 처리할 수 있음
- `: "${1:?missing argument, aborting!}"`는 `$1`이 없거나 비어 있으면 진단 메시지를 **stderr**에 출력하고 0이 아닌 상태로 종료함
- `${VAR:=default}`를 `:`의 인수로 전달하면 확장은 실행하되 결과 문자열은 버리므로, 확장 결과를 명령으로 실행하지 않고 **기본값만 설정**할 수 있음
- 리디렉션을 통한 파일 비우기와 접근 가능 여부 검사, `trap`의 빈 명령, `set -u` 환경의 변수 검사, 비어 있는 조건 분기에도 `:`를 활용할 수 있음
- `: "${VAR:=default}"`는 변수명을 한 번만 써서 오타 가능성을 줄이고, `while:`에서는 항상 성공하는 조건이 되어 **무한 루프**를 표현함

---

### 널 명령과 매개변수 확장
- [`:`](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_16)는 인수를 평가한 뒤 결과를 버리는 **널 명령** 내장 명령임
  - 1971년 [Thompson shell](https://en.wikipedia.org/wiki/Thompson_shell#Design)까지 거슬러 올라가며, 당시에는 [레이블](https://www.in-ulm.de/~mascheck/bourne/PWB/goto.1.html)이자 Unix 최초의 주석 표식으로도 쓰였음
- 네 줄짜리 조건문 대신 다음 한 줄로 필수 인수를 검사할 수 있음

```sh
: "${1:?missing argument, aborting!}"
echo "Hello $1!"
```

- [매개변수 확장](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02) 구문 `${name:?diagnostic}`는 `$name`이 설정되지 않았거나 비어 있는지 검사함
  - 값이 없으면 `diagnostic`을 **stderr**에 출력하고 셸을 0이 아닌 상태로 종료함
  - 값이 있으면 `$name`과 같은 결과를 냄
- 널 명령 없이 `${HELLO:=123}`만 실행하면 확장 결과인 `123`을 명령으로 취급해 `command not found`가 발생함
  - `: ${HELLO:=123}`는 확장을 평가해 `HELLO=123`을 설정하면서 그 결과는 버림
- `: "${DATA_DIR:=/var/data}"`는 `DATA_DIR="${DATA_DIR:-/var/data}"`와 달리 변수명을 한 번만 적으므로 `DATA_DRI` 같은 **오타 가능성**을 줄일 수 있음

### `:`를 활용하는 방법
- ## 기본값 설정
  - 확장 결과를 실행하지 않고 버리면서 변수의 기본값을 설정함

```sh
: "${DATA_DIR:=/var/data}"
: "${RETRIES:=3}"
```

- ## 파일 비우기와 접근 검사
  - 리디렉션과 결합하면 하나 이상의 파일을 **비울 수 있음**

```sh
: > error.log
: > error.log > access.log
```

  - 서브셸과 리디렉션을 이용해 파일의 읽기·쓰기 가능 여부도 검사할 수 있음

```sh
( : < dataset.json ) && echo YES
( : >> result.json ) && echo YES
```

- ## 빈 명령이 필요한 자리
  - `trap`처럼 문법상 명령이 필요하지만 실제 작업은 하지 않아야 할 때 사용할 수 있음

```sh
trap : INT
sleep 60
```

  - 조건문에서 비워 둘 분기에도 배치 가능함

```sh
if some-command; then
    :
else
    echo "command failed"
fi
```

- ## 여러 변수 검사
  - `set -u`가 활성화된 상태에서 여러 변수가 설정됐는지 한 번에 검사함

```sh
set -u
: "$DEPLOY_ENV" "$HOST"
```

- ## 무한 루프
  - `:`는 항상 성공하는 조건이므로 **무한 루프**를 간결하게 작성할 수 있음

```sh
while :; do
  echo "I love colons"
  sleep 1
done
```

## Comments



### Comment 62389

- Author: neo
- Created: 2026-07-26T09:02:36+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/eidh3u/shell_colon_does_nothing_use_it_anyway) 
- 프롬프트를 다음처럼 구성하면 **한 줄 전체를 복사해 붙여넣어도** 프롬프트 부분은 무시되고 명령만 실행됨  
  `: hayalci@tassadar ~/src/dool ; jj rebase -s dxw -d mrn`
  - Plan 9에서 착안해 셸의 `autocd` 옵션과 다음 형식도 사용함  
    `~/directoryname; &lt;command&gt;`  
    셸의 명령 줄을 복사할 때마다 명령을 원래 실행했던 디렉터리로 계속 `cd`하게 됨
  - `zsh`에서는 **보이지 않는 줄 바꿈 없는 공백**을 붙여넣으면 왼쪽 내용을 지우도록 설정함  
    ```zsh  
    nbsp=$'\u00A0'  
    PS1="...$nbsp"  
    bindkey -s $nbsp '^u'  
    ```
- Makefile에서 보기 좋게 출력할 때 콜론을 자주 사용함  
  ```make  
  out/%.o: src/%.c  
      @echo CC $@  
      @$(CC) -c -o $@ $<  
  ```  
  이 방식은 `make`가 여러 `echo` 프로세스를 동시에 실행하면서 같은 스트림에 출력해 서로 간섭할 수 있음. 다음처럼 바꾸면 자식 프로세스가 아니라 **`make` 프로세스 자체가 출력**함  
  ```make  
  out/%.o: src/%.c  
      : CC $@  
      @$(CC) -c -o $@ $<  
  ```
- 셸 스크립트에서 이 기법을 봤지만 `man :`이나 `whatis :`으로는 유용한 문서를 찾기 어려웠음  
  `true` 명령과 비슷하지만 `--help`, `--version` 등에 특별히 반응하지 않고 글자 수도 더 적다는 차이가 있음
  - Bash 내장 명령은 `man` 대신 [`help`](https://www.gnu.org/software/bash/manual/bash.html#index-help)로 찾아야 함  
    ```  
    $ help :  
    :: :  
        Null command.

        No effect; the command does nothing.

        Exit Status:  
        Always succeeds.  
    ```
  - Fish에서 `:`는 말 그대로 **`true`의 별칭**임
- 콜론 없이도 매개변수 확장은 일어나는데, 굳이 **널 명령**이 필요한 이유가 궁금함
  - 매개변수 확장은 그대로 일어나지만, 널 명령처럼 결과를 소비하는 구문이 없으면 셸이 확장된 문자열을 **실행할 명령**으로 취급함. 이 내용을 [FAQ](https://refp.se/articles/your-shell-and-the-magic-colon#frequently-asked-questions)에도 추가함  
    ```  
    % ${HELLO:=123}  
    zsh: command not found: 123  
    ```  
    ```  
    % : ${HELLO:=123}  
    % echo $HELLO  
    123  
    ```
  - 보간된 문자열의 결과가 실행할 명령으로 해석됨  
    ```sh  
    #!/bin/sh  
    "${1:?missing argument, aborting!}"  
    ```  
    ```  
    $ sh foo.sh sh  
    sh-5.3$  
    ```
- 명령을 입력하다가 나중에 다시 실행하고 싶을 때 줄 맨 앞에 콜론을 붙여 실행 기록에 저장함. 이후 기록에서 해당 줄을 찾아 첫 글자만 지우면 실제로 실행할 수 있음  
  다만 인수를 평가하면서 생기는 **부수 효과**에 활용할 생각은 못 했음
  - `:` 대신 `#`을 붙여 **주석으로 저장**할 수도 있음. 나중에 실행할 내용이라면 그 안의 표현식을 미리 평가하지 않는다는 장점이 있음
  - zsh에서는 Meta-q 또는 Alt-q로 현재 줄을 잠시 치우고 다른 명령을 실행한 뒤, 끝나면 원래 줄을 명령줄 버퍼로 되돌릴 수 있음  
    https://nathangrigg.com/2014/04/zsh-push-line-or-edit/
- macOS에서 아직 **Bash 3**을 사용하고 있으며 다음 오류가 발생함  
  `-bash: !}": event not found`
  - `"!"` 사용을 제거하면 동작하는지 궁금함
- [Con-colon-sion](https://refp.se/articles/your-shell-and-the-magic-colon#con-colon-sion)의 다음 코드는 `while true; do...`보다 사람을 혼란스럽게 만들 가능성이 큼  
  ```bash  
  while : colons are more than punctuation; do  
    echo "I love colons"  
    sleep 1  
  done  
  ```  
  `while true; do`는 `while :; do`보다 세 글자 길 뿐이라 충분히 짧으며, 저 코드는 저자가 전달하려는 요점에 적합한 예제로 보이지 않음
  - 그대로 따르라는 예제가 아니라 **말장난**으로 넣은 코드임. 이 코드를 이해할 수 있다면 널 명령을 아는 것이고, 콜론은 실제로 문장부호 이상의 의미가 있음
  - 원래 보여주려던 것은 다음과 같은 **무한 반복문**이지만, 멋있게 표현하려다 요점을 놓친 듯함  
    ```bash  
    while :; do  
        something  
    done  
    ```
