트랙
/
Bash
Bash
/
학습 과정
/
리디렉션
리디

리디렉션 에서 Bash

{other: "%{count}개의 연습 문제"}

리디렉션 소개

명령줄 인터페이스 세계에서 프로그램은 흔히 세 가지 표준 데이터 스트림과 상호작용해요.

  1. 표준 입력(stdin): 프로그램이 입력을 받는 곳이에요(보통 키보드에서 받아요).
  2. 표준 출력(stdout): 프로그램이 일반 출력을 내보내는 곳이에요(보통 터미널 화면으로 보내요).
  3. 표준 오류(stderr): 프로그램이 오류 메시지를 내보내는 곳이에요(보통 터미널 화면으로 보내요).

파이프라인과 명령 목록 챕터에서 이 스트림들을 소개했던 것, 기억나요?

Note

파이프라인도 리디렉션의 한 형태로 볼 수 있어요. 한 프로그램의 표준 출력이 다른 프로그램의 표준 입력으로 곧바로 전달되니까요. 파이프라인은 이미 다뤘어요. 이번 개념에서는 파일로 보내는 리디렉션과 파일에서 받아오는 리디렉션을 다뤄요.

셸 리디렉션은 이 스트림들의 목적지를 바꿀 수 있게 해 주는 강력한 방법이에요. 프로그램이 키보드에서 읽거나 화면에 쓰도록 하는 대신, 파일에서 입력을 받아오거나 출력을 파일로 보낼 수 있어요. 덕분에 프로그램이 데이터와 상호작용하는 방식을 훨씬 유연하고 세밀하게 제어할 수 있어요.

주요 리디렉션 연산자

가장 흔히 쓰이는 리디렉션 연산자와 그 역할을 살펴볼까요.

> (출력 리디렉션)

  • 목적: 명령의 표준 출력(stdout)을 파일로 보내요.

  • 동작:

    • 파일이 없으면 새로 만들어요.
    • 파일이 있으면 내용을 덮어써요.
  • 예:

    # Sends the output of 'ls -l' to 'file_listing.txt'
    ls -l > file_listing.txt
    
Caution

리디렉션은 명령이 실행되기 전에 수행돼요. 따라서 읽어야 하는 파일과 똑같은 파일로 리디렉션할 수는 없어요.

date > date.txt         # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!

위 예시의 두 번째 명령을 보면,

  1. Bash가 먼저 리디렉션에 지정된 파일을 잘라내요. 그러면 이전 내용이 사라지고 빈 파일만 남아요.
  2. 그다음 Bash가 방금 비워진 파일을 읽어요.
  3. 그러고 나서 그 내용(즉, 아무것도 없음)을 다시 파일에 써요.

>> (출력 추가 리디렉션)

  • 목적: 명령의 표준 출력(stdout)을 파일 끝에 추가해요.

  • 동작:

    • 파일이 없으면 새로 만들어요.
    • 파일이 있으면 출력을 파일 끝에 추가해요.
  • 예:

    # Adds "Another line" to the end of the file
    echo "Another line" >> file_listing.txt
    

< (입력 리디렉션)

  • 목적: 명령의 표준 입력(stdin)을 파일에서 받아오도록 해요.

  • 동작: 명령이 키보드 대신 지정한 파일에서 입력을 읽어요.

  • 예:

    # 'tr' reads from 'lowercase.txt' and
    # output is redirected to 'uppercase.txt'
    tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
    

2> (오류 리디렉션):

  • 목적: 명령의 표준 오류(stderr)를 파일로 보내요.
  • 동작: 오류 메시지가 터미널 대신 지정한 파일로 전달돼요.
  • 예:
    # Error message from 'rm' is sent to 'error_log.txt'
    rm non_existent_file 2> error_log.txt
    

2>>를 쓰면 표준 오류를 파일에 _추가_할 수 있어요.

그 밖의 리디렉션

stdin과 stderr 둘 다 합칠 수 있는 리디렉션도 있어요. 자세한 내용은 매뉴얼에서 확인해요.

/dev/null

/dev/null은 다음과 같은 특별한 파일이에요.

  • 읽으면 빈 파일로 보여요.
  • 거기에 쓰는 모든 데이터를 버려요.

때로는 "비트 버킷"이라고 부르기도 해요. 출력이나 오류를 없애는 데 유용해요.

some_command > /dev/null  # Discards stdout
some_command 2> /dev/null # Discards stderr

# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null

리디렉션 조합하기

여러 리디렉션을 한 번에 지정할 수 있어요.

some_command < input.txt > output.txt 2> error.txt

리디렉션은 복사할 수도 있어요.

# send stderr to the same destination as stdout
some_command > output.txt 2>&1

2>&1은 "stderr를 stdout이 현재 가리키고 있는 곳 으로 리디렉션한다"고 읽으면 돼요. Bash는 리디렉션 지시를 엄격하게 왼쪽에서 오른쪽으로 처리해요. 그래서 다음과 같은 것도 할 수 있어요.

# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
Advanced

파일 디스크립터

셸 프로그래밍과 Linux/Unix 같은 운영체제에서 파일 디스크립터(FD)는 열린 파일이나 입출력(I/O) 자원을 식별하거나 다루기 위한 핸들 역할을 하는 음이 아닌 정수예요. 운영체제가 열린 파일과 데이터 스트림을 추적하기 위해 사용하는 이름표나 참조 번호라고 생각하면 돼요.

리디렉션의 왼쪽에 보이는 숫자가 바로 파일 디스크립터예요.

표준 입출력 스트림에는 처음 세 개의 파일 디스크립터가 할당돼요.

  • 표준 입력은 FD 0
  • 표준 출력은 FD 1
  • 표준 오류는 FD 2

새 파일 디스크립터는 exec 명령과 리디렉션 연산자로 설정하거나 만들 수 있어요.

# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt

# then redirect both stdout and file descriptor 3
echo "some debug message" >&3  # displayed in the terminal
some_command  2>&1 # stdout and stderr send to 'log.txt'

이 기법은 꽤 복잡해 보이지만, 스크립트가 다른 소프트웨어 패키지에 의해 실행되고 표준 출력이 그 소프트웨어에 자동으로 캡처되는 상황에서는 아주 유용할 수 있어요. 이 트랙의 단위 테스트를 실행하는 데 쓰이는 bats 명령도 이렇게 동작해요. bats는 테스트의 stdout과 stderr를 캡처하지만, FD 3으로 보낸 디버그 메시지는 터미널에 표시돼요.

정리

리디렉션은 왜 유용할까요?

  • 출력 저장: 나중에 확인하거나 처리하려고 명령의 결과를 저장해요.
  • 로깅: 디버깅을 위해 오류 메시지를 기록해요.
  • 자동화: 한 명령의 출력을 다른 명령의 입력으로 사용하며 명령을 연결해요.
  • 필터링: 원하지 않는 출력을 버려요.
  • 일괄 처리: 직접 입력하는 대신 파일의 데이터를 처리해요.
  • 스크립팅: 견고한 셸 스크립트를 작성하려면 리디렉션이 꼭 필요해요.

셸 리디렉션을 사용하면 프로그램이 데이터와 상호작용하는 방식을 세밀하게 제어할 수 있어, 복잡한 워크플로를 만들고 정보를 효과적으로 관리할 수 있어요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요