셸은 프로그램의 입출력을 파일과 다른 프로그램으로 잇는다. 이 연결은 프로그램을 실행하기 전에 셸이 만들어 둔다.

프로그램은 번호가 붙은 입출력을 가진다. 0은 표준입력, 1은 표준출력, 2는 표준오류다. 보통 출력은 결과, 오류는 진단 메시지다.

파일로 보내고 파일에서 읽기

Bash
echo hello > out.txt
echo more >> out.txt
wc -l < out.txt

`>`는 파일을 새로 만든다. 이미 있으면 내용을 비우고 다시 쓴다. `>>`는 끝에 붙인다. `<`는 그 파일을 표준입력으로 연다.

Bash
make > build.log 2> error.log
make > build.log 2>&1
grep noise app.log > /dev/null

`2>`는 표준오류만 다른 파일로 보낸다. `2>&1`은 표준오류를 표준출력이 가는 곳으로 보낸다. `> build.log 2>&1`처럼 파일로 보내는 쪽을 먼저 적어야 둘 다 그 파일로 간다.

`/dev/null`은 받아도 버리는 파일이다. 보고 싶지 않은 출력을 여기로 보낸다.

파이프

`|`는 앞 명령의 표준출력을 뒤 명령의 표준입력으로 잇는다. 표준오류는 파이프로 넘어가지 않는다. 오류까지 넘기려면 파이프 앞에 `2>&1`을 둔다.

Bash
dmesg | tail -n 20
dmesg 2>&1 | tail -n 20
sort access.log | uniq -c | sort -nr | head

find의 이름을 다른 명령에 안전하게 넘길 때는 널 문자로 구분한다. 이름에 공백이 있어도 한 덩어리로 남는다.

Bash
find . -name '*.txt' -print0 | xargs -0 wc -l

명령 잇기

Bash
mkdir work && cd work
cd missing || echo 실패
cmd1 ; cmd2

`&&`는 앞 명령이 0으로 끝났을 때만 뒤를 실행한다. `||`는 앞 명령이 실패했을 때 뒤를 실행한다. `;`는 성공 여부와 상관없이 다음으로 넘어간다.

글롭

`*`, `?`, 대괄호는 셸이 파일 이름으로 바꾼 뒤 명령에 넘긴다.

Bash
ls *.log
ls file?.txt
ls data-[0-9].csv

`*`는 빈 문자열을 포함한 아무 길이, `?`는 한 글자다. 점으로 시작하는 이름은 `*`에 들어가지 않는다. 맞는 이름이 없으면 bash는 패턴 문자열을 그대로 넘긴다.

공백이 있는 이름과 변수는 따옴표로 감싼다.

Bash
rm -- "$name"

따옴표가 없으면 셸이 공백에서 인자를 자른다.

여러 줄의 입력을 명령에 바로 넣을 때는 히어 도큐먼트를 쓴다. 끝 표시로 적은 단어가 혼자 있는 줄에서 끝난다.

Bash
cat <<'EOF'
$HOME 은 여기서 확장되지 않는다.
EOF

시작 단어를 작은따옴표로 감싸면 본문의 `$`와 역따옴표를 셸이 해석하지 않는다. 따옴표 없이 `<<EOF`로 열면 확장된다.