단순 명령 · 파이프라인 · 리스트 — 명령을 잇는 기호들
이 글은 GNU Bash 매뉴얼 3.2 Shell Commands 가운데 예약어·단순 명령·파이프라인·리스트(3.2.1–3.2.4)를, 처음 배우는 분도 따라올 수 있게 쉬운 말로 풀어 정리합니다. 한 줄짜리 명령을 넘어, |·&&·||·;·&로 여러 명령을 어떻게 이어 붙이는지 가 핵심입니다.
이 글을 읽고 나면
단순 명령이 “명령 이름 + 인자들”로 구성된다는 점을 설명할 수 있습니다.
파이프(|)가 앞 명령의 출력을 뒤 명령의 입력으로 넘긴다는 것을 이해합니다.
&& / || / ; / &의 차이를 구분하고, 상황에 맞게 고를 수 있습니다.
파이프라인의 성공/실패가 기본으로 “맨 오른쪽”만 본다는 함정을 압니다.
큰 그림: 명령을 쌓는 세 층
셸에서 자주 쓰는 명령 구조를 층으로 나누면 이해하기 쉽습니다.
Text
① 단순 명령 echo hello world └─ 명령 하나 + 인자들 ② 파이프라인 cmd1 | cmd2 | cmd3 └─ 앞 출력 → 뒤 입력으로 연결 ③ 리스트 A && B || C ; D & └─ 성공/실패·순서·백그라운드로 여러 파이프를 이어 붙임
이전 글에서 셸이 한 줄을 “나누고 → 펼치고 → 실행”한다고 했습니다. 이번 글은 그렇게 실행되는 명령들을 어떻게 이어 붙이는지 에 초점을 둡니다.
예약어 — 특별한 뜻을 가진 단어
if, for, while, then, do, !, [[ 같은 단어는 셸이 특별한 뜻 으로 알아듣는 예약어입니다. 보통 따옴표 없이, 그리고 명령의 첫 단어 로 나올 때 예약어로 취급됩니다.
예약어 예 |
나중에 다루는 용도 |
|---|---|
if then else fi |
조건 분기 |
for while until do done |
반복 |
! |
“성공/실패를 뒤집기” (파이프 앞에 자주 씀) |
[[ ]] |
Bash 조건식 |
{ } |
명령 묶기 |
지금은 “이런 단어들이 있다” 정도만 기억해도 충분합니다. 따옴표로 감싸면("if") 일반 글자가 되어, 예약어로 동작하지 않습니다.
단순 명령 — 가장 자주 쓰는 형태
단순 명령 은 공백으로 나뉜 단어들의 나열입니다.
Bash
printf '%s\n' apple banana cherry
첫 단어 → 실행할 명령 (printf)
나머지 단어 → 그 명령에 넘기는 인자 ('%s\n', apple, …)
명령이 끝나면 종료 코드 가 남습니다.
종료 코드 |
의미 (관례) |
|---|---|
0 |
성공 |
0이 아님 |
실패 (또는 “찾지 못함” 등 상황별 코드) |
이 성공/실패 값이 바로 아래에서 배울 && / ||의 판단 기준이 됩니다.
파이프라인 — 앞의 결과를 뒤로 흘려보내기
파이프라인 은 명령을 |로 이은 것입니다.
Bash
printf '%s\n' apple banana cherry | grep a | wc -l
동작 방식은 간단합니다.
Text
printf 가 만든 출력 ──│──▶ grep 의 입력 grep 가 만든 출력 ──│──▶ wc 의 입력
앞에서 나온 글자가, 파일로 저장하지 않고도 바로 다음 명령의 입력 이 됩니다. 데이터를 흘려보내는 호스(pipe)를 상상하면 됩니다.
알아 둘 세부 사항입니다.
항목 |
쉬운 설명 |
|---|---|
기본 종료 코드 |
맨 오른쪽 명령 의 성공/실패만 전체가 됩니다 |
pipefail |
켜 두면, 중간 단계가 실패해도 전체 실패로 봅니다 |
! 를 앞에 |
성공/실패를 뒤집습니다 (! true → 실패처럼) |
|& |
표준 출력뿐 아니라 에러 출력도 파이프로 (Bash 4+; 2>&1 | 와 같음) |
리스트 — 명령을 “언제, 어떤 순서로” 실행할지
리스트 는 파이프라인(또는 단순 명령)을 ; · & · && · ||로 이은 것입니다. 실무에서 가장 많이 쓰는 네 가지를 비교합니다.
; — 순서대로, 성공/실패와 무관
Bash
echo first; echo second
앞이 끝나야 뒤가 시작합니다. 앞이 실패해도 뒤는 그대로 실행됩니다.
&& — 앞이 성공할 때만 뒤 실행
Bash
mkdir -p out && cp file.txt out/
“만들기에 성공했을 때만 복사한다”처럼 전제 조건 을 걸 때 씁니다. 앞이 실패하면 뒤는 건너뜁니다.
|| — 앞이 실패할 때만 뒤 실행
Bash
grep -q pattern file.txt || echo "not found"
“찾기에 실패했을 때만 안내 메시지를 낸다”처럼 대체 동작·에러 처리 에 씁니다.
& — 백그라운드(비동기)
Bash
long_job &
셸이 끝날 때까지 기다리지 않고 다음으로 넘어갑니다. 스크립트에서는 종료 시점을 wait로 맞추는 일이 많아, 자세한 내용은 이후 Job Control 글에서 다룹니다. 지금은 “앞에 &를 붙이면 기다리지 않는다” 정도만 기억하세요.
한눈에 비교
기호 |
앞이 성공하면 |
앞이 실패하면 |
기다림 |
|---|---|---|---|
; |
뒤 실행 |
뒤 실행 |
앞이 끝날 때까지 |
&& |
뒤 실행 |
뒤 건너뜀 |
앞이 끝날 때까지 |
|| |
뒤 건너뜀 |
뒤 실행 |
앞이 끝날 때까지 |
& |
(백그라운드) |
(백그라운드) |
기다리지 않음 |
우선순위는 대략 && / ||가 같고, 그다음 ; / &입니다. 복잡한 한 줄보다, 읽기 쉽게 줄을 나누는 편이 유지보수에 유리합니다.
실행 예제
아래 스크립트는 단순 명령, 파이프, && / || / ;, 그리고 파이프 종료 코드의 차이를 한 화면에서 보여 줍니다.
Bash
#!/usr/bin/env bash # 단순 명령 · 파이프 · && / || / ; 를 한 화면에서 비교합니다. set -eu echo "=== 1) 단순 명령: 명령 + 인자 ===" printf '%s\n' apple banana cherry # (1) 첫 단어=명령, 나머지=인자 echo echo "=== 2) 파이프라인: 앞 출력 → 뒤 입력 ===" printf '%s\n' apple banana cherry | grep a | wc -l # (2) a 가 들어간 줄 개수 echo echo "=== 3) && : 앞이 성공할 때만 뒤 실행 ===" true && echo "left ok → right runs" # (3) true 는 항상 성공(종료 코드 0) echo echo "=== 4) || : 앞이 실패할 때만 뒤 실행 ===" false || echo "left failed → right runs" # (4) false 는 항상 실패(비0) echo echo "=== 5) ; : 성공/실패와 관계없이 순서대로 ===" echo first; echo second # (5) 앞이 끝나야 뒤가 시작 echo echo "=== 6) 파이프 종료 코드: 기본은 마지막만 ===" set +e # (6) 아래 데모에서 실패해도 스크립트 중단 방지 set +o pipefail # (7) 기본: 파이프 결과는 맨 오른쪽 기준 false | true echo "without pipefail: exit=$?" # (8) 대개 0 (true 의 결과) set -o pipefail # (9) 중간에 실패한 단계도 실패로 취급 false | true echo "with pipefail: exit=$?" # (10) 대개 1 (false 의 결과) echo echo "ok — 명령을 잇는 기호마다 의미가 다릅니다."
주요 라인별 설명
1: 단순 명령 — printf가 명령이고, 뒤는 모두 인자입니다.
2: |로 세 단계를 이어, 앞 출력이 뒤 입력이 됩니다.
3: && — 왼쪽이 성공(0)일 때만 오른쪽이 실행됩니다.
4: || — 왼쪽이 실패(비0)일 때만 오른쪽이 실행됩니다.
5: ; — 성공/실패와 무관하게 앞→뒤 순서로 실행됩니다.
6–8: pipefail이 꺼져 있으면 false | true의 종료 코드는 오른쪽(true) 기준이라 0에 가깝습니다.
9–10: pipefail을 켜면 중간 실패가 전체에 반영되어 비0이 됩니다.
실행하면 대략 이런 결과가 나옵니다.
Text
=== 1) 단순 명령: 명령 + 인자 === apple banana cherry === 2) 파이프라인: 앞 출력 → 뒤 입력 === 2 === 3) && : 앞이 성공할 때만 뒤 실행 === left ok → right runs === 4) || : 앞이 실패할 때만 뒤 실행 === left failed → right runs === 5) ; : 성공/실패와 관계없이 순서대로 === first second === 6) 파이프 종료 코드: 기본은 마지막만 === without pipefail: exit=0 with pipefail: exit=1
(wc -l 숫자의 앞쪽 공백은 환경에 따라 조금 다를 수 있습니다. 값은 “2”입니다.)
헷갈리기 쉬운 부분
&&와 ;를 혼동 — ;는 앞이 실패해도 뒤를 돌립니다. “성공했을 때만” 이려면 &&입니다.
||를 “그리고”처럼 읽기 — ||는 “또는/실패 시”에 가깝습니다. 둘 다 성공해야 하면 &&를 쓰세요.
파이프 중간 실패를 놓침 — 기본은 맨 오른쪽만 봅니다. 중요한 파이프에는 set -o pipefail을 고려하세요.
|&가 안 됨 — 일부 환경(예: 오래된 Bash 3.2)에는 없습니다. 같은 뜻으로 2>&1 |를 쓰면 됩니다.
화면에 출력이 없어도 실패일 수 있음 — 분기할 때는 출력보다 종료 코드 를 기준으로 생각하세요.
한 줄 요약
**단순 명령은 ‘이름 + 인자’이고, |는 출력을 다음 입력으로 흘려보내며, &&/||/;/&는 언제·어떤 순서로 이을지를 정합니다. 파이프의 성공/실패는 기본이 맨 오른쪽이니, 필요할 때 pipefail을 기억하세요.