리눅스의 명령줄 인터페이스(CLI)는 시스템에서 다양한 작업을 강력하고 유연하게 수행할 수 있게 해주는 도구입니다. 리눅스는 유닉스의 철학을 기반으로 만들어졌기 때문에, 터미널 자체에 수많은 강력한 기능이 내장되어 있습니다.
그중에서도 가장 핵심적인 두 가지 기능이 바로 파이핑(piping)과 리디렉션(redirection)입니다. 이 두 기능을 활용하면 명령어의 입력과 출력을 다른 명령어나 파일로 자유롭게 연결할 수 있습니다.
이 글에서는 리눅스에서 파이핑과 리디렉션이 무엇인지 살펴본 뒤, 실제로 이를 어떻게 활용하는지 예제와 함께 깊이 있게 알아보겠습니다.
시작하기 전에
이 가이드를 온전히 이해하려면 다음 사항이 필요합니다.
- 리눅스 운영체제에 대한 기본적인 이해
- 리눅스 명령줄을 다뤄본 기초 경험
- 명령어를 직접 실행해 볼 수 있는 리눅스 환경
리눅스가 처음이거나 개념을 다시 정리하고 싶다면, 먼저 리눅스 명령줄 기초 튜토리얼을 참고하는 것을 추천합니다.
리눅스에서 파이핑(Piping)이란?
사용 방법을 알아보기 전에, 파이핑이 정확히 무엇을 의미하는지 짚고 넘어가겠습니다. 파이핑은 한 명령어의 출력을 다른 명령어의 입력으로 전달하는 행위입니다. 표준 출력(standard output)이나 표준 오류(standard error)를 한 명령어에서 다른 명령어로 넘길 수 있습니다.
가장 단순한 예는 한 명령어의 결과물을 그대로 다음 명령어의 입력으로 사용하는 것입니다. 이때 파이프(|) 메타문자를 사용합니다.
메타문자라는 용어가 낯설다면, 명령줄에서 특별한 의미를 가지는 문자라고 생각하면 됩니다. 파이프(|) 외에도 리눅스에는 다양한 메타문자가 존재합니다. 대표적으로 작거나(<), 크거나(>), 앰퍼샌드(&) 등이 있습니다.
파이핑의 기본 문법
pipe를 사용하는 기본 문법은 다음과 같습니다.
command1 | command2 | command3 | ... | commandN
위 문법에서 터미널은 명령어를 왼쪽에서 오른쪽 순서로 실행합니다. 먼저 command1이 실행되고, 그 출력이 command2의 입력으로 전달됩니다. 이어서 command2의 출력이 command3의 입력이 되는 방식입니다. 파이핑의 장점은 원하는 만큼 명령어를 계속 연결할 수 있다는 점입니다.
파이핑 실전 예제
pipe를 활용해 다양한 작업을 수행하는 몇 가지 예제를 살펴보겠습니다.
1. 파일과 디렉터리 개수 세기
ls -l | wc -l
위 예제에서 첫 번째 부분은 ls 명령어로 현재 디렉터리의 모든 파일과 디렉터리를 나열합니다. 추가된 -l 옵션은 내용을 상세 목록(long listing) 형식으로 보여달라는 의미입니다.
그런 다음 ls -l의 출력이 두 번째 부분으로 전달됩니다. wc -l 명령어는 앞선 출력의 줄 수를 세어 결과를 터미널에 출력합니다. 즉, 파일과 디렉터리의 총 개수를 알려주는 것입니다.
2. 파일과 디렉터리 목록 정렬하기
ls | sort
위 명령어에서 ls는 현재 디렉터리의 파일과 디렉터리 목록을 출력하고, 이 목록이 sort 명령어로 전달되어 알파벳순으로 정렬된 후 터미널에 표시됩니다.
3. 파일에서 중복 없는 단어 정렬하여 출력하기
cat words.txt | sort -r | uniq
세 번째 예제는 두 개의 파이프로 연결된 세 개의 명령어를 포함합니다. 첫 번째 명령어는 단어 목록이 담긴 words.txt 파일의 내용을 출력합니다.
그 출력은 sort -r 명령어로 전달되어 역알파벳순으로 정렬됩니다. 마지막으로 정렬된 단어들이 uniq 명령어로 넘어가 중복이 제거된 고유한 단어만 출력됩니다.
파이핑은 언제, 왜 사용해야 할까?
파이핑은 문법 자체보다 본질을 이해하는 것이 더 중요합니다. 문법은 매우 간단하지만, 제대로 활용하려면 그 목적을 알아야 합니다.
파이핑의 목적은 한 명령어의 출력을 다른 명령어의 입력으로 사용하며 명령어를 연결(chain)하는 것입니다.
반면, 서로 관련 없는 명령어를 단순히 순차적으로 실행하고 싶을 때는 파이핑이 적합하지 않습니다. 그런 경우에는 아래처럼 세미콜론(;)으로 명령어를 구분해 작성하세요.
command1 ; command2 ; ... ; commandN
리눅스에서 리디렉션(Redirection)이란?
리디렉션은 명령어의 입력이나 출력이 어디로 향할지 지정하는 행위입니다. 기본적으로 명령어는 표준 입력에서 데이터를 받아 표준 출력으로 결과를 내보냅니다.
리디렉션이 특히 유용한 분야 중 하나는 명령어와 파일을 함께 다룰 때입니다. 예를 들어 명령어의 출력을 터미널에 표시하는 대신 파일에 저장할 수 있고, 반대로 특정 파일을 명령어의 입력으로 지정할 수도 있습니다.
파이핑과 마찬가지로 리눅스는 리디렉션을 위한 특수 문자를 제공합니다. 주요 파일 리디렉션 문자와 그 역할은 다음과 같습니다.
>– 명령어의 출력을 지정한 파일로 보냅니다.<– 지정한 파일의 내용을 명령어의 입력으로 보냅니다.>>– 명령어의 출력을 지정한 파일로 보내며, 파일이 이미 존재하고 내용이 있으면 덮어쓰지 않고 이어서 추가(append)합니다.2>– 명령어의 오류 메시지를 지정한 파일로 보냅니다.2>>– 명령어의 오류 메시지를 지정한 파일로 보내며, 파일이 존재하면 기존 내용 뒤에 추가합니다.&>– 표준 출력과 표준 오류를 모두 지정한 파일로 보냅니다.&>>– 표준 출력과 표준 오류를 모두 지정한 파일로 보내며, 파일이 존재하면 내용을 추가합니다.
이제 각 리디렉션 문자를 하나씩 자세히 살펴보겠습니다.
1. >를 이용한 출력 리디렉션
> 기호는 명령어의 출력을 특정 파일로 보낼 때 사용합니다. 이 기호를 사용하면 기존 파일에 출력을 저장할 수 있으며, 파일이 존재하지 않으면 자동으로 새 파일을 생성합니다.
단, 기존 파일에 쓸 때는 주의해야 합니다. 경고 없이 기존 내용이 통째로 덮어써지기 때문입니다.
출력 리디렉션은 다음 문법으로 수행합니다.
command > file
command의 실행 결과가 표준 출력(즉, 터미널 화면) 대신 file에 기록됩니다. 실제 예제는 다음과 같습니다.
ls -a > contents.txt
위 명령어를 실행하면 현재 디렉터리의 항목 목록(점 파일, 디렉터리, 파일 포함)이 contents.txt 파일에 저장됩니다. 리디렉션 때문에 터미널에는 아무런 출력도 표시되지 않습니다.
2. >>를 이용한 출력 리디렉션
>> 역시 명령어의 출력을 파일로 보냅니다. 하지만 단일 >와 달리, >>는 기존 파일에 쓸 때 내용을 덮어쓰지 않고 끝에 추가합니다. 파일이 존재하지 않으면 새로 생성합니다.
문법은 다음과 같습니다.
command >> file
앞선 예제와 동일한 작업을 >>로 수행하는 예는 다음과 같습니다.
ls -a >> contents.txt
3. <를 이용한 입력 리디렉션
명령줄에서 < 문자를 사용하면 키보드 대신 파일의 내용을 명령어의 입력으로 전달할 수 있습니다. 입력 리디렉션의 문법은 다음과 같습니다.
command < file
실제 사용 예는 다음과 같습니다.
wc -w < files.txt
위 예제에서는 files.txt를 wc -w 명령어의 입력으로 전달해 파일의 단어 수를 셉니다. 다만 많은 경우 입력 리디렉션 문자가 없어도 동일하게 동작하는데, 이것이 기본 동작이기 때문입니다. 예를 들어 위 명령어는 아래와 같습니다.
wc -w files.txt
4. 2>와 2>>를 이용한 오류 리디렉션
명령줄 작업 중에는 오류를 만나는 경우가 흔합니다. 예를 들어 적절한 권한 없이 파일을 실행하려 할 때가 그렇습니다. 터미널이 오류를 화면에 출력하도록 두는 대신, 오류 리디렉션 문자를 사용해 오류 메시지가 어디로 갈지 지정할 수 있습니다.
오류를 보내기 좋은 곳은 오류 전용 로그 파일입니다. 다음은 존재하지 않는 디렉터리의 파일 목록에 접근하려는 간단한 예제입니다.
ls nonexistent 2> error.txt
위 예제에서 nonexistent라는 이름의 파일이 없기 때문에 터미널은 오류를 발생시킵니다. 하지만 오류 리디렉션 문자 덕분에 오류가 콘솔에 출력되지 않고 error.txt 파일에 저장됩니다. 오류가 발생하지 않으면 파일은 비어 있게 됩니다.
기존 파일의 내용을 덮어쓰지 않고 오류를 추가하려면 2> 대신 2>>를 사용하세요.
5. &>와 &>>를 이용한 출력·오류 동시 리디렉션
표준 출력과 표준 오류 중 무엇을 리디렉션할지 일일이 선택하는 대신, &>를 사용하면 둘을 동시에 처리할 수 있습니다. &>는 출력 리디렉션(>)과 오류 리디렉션(2>)을 합친 축약형이라고 생각하면 됩니다.
&>의 문법은 다음과 같습니다.
command &> output.txt
command의 출력 또는 오류가 output.txt 파일에 기록됩니다. 예제를 살펴보겠습니다.
ls sample &> output.txt
위 명령어에서 sample 디렉터리가 존재하지 않거나, 존재하더라도 읽기 권한이 없다면 해당 오류가 output.txt에 기록됩니다. 반대로 디렉터리가 존재하고 읽기 권한이 있다면 그 내용이 output.txt에 저장됩니다.
&>>를 사용하면 파일이 이미 존재하고 내용이 있을 때 덮어쓰지 않고 출력을 추가할 수 있습니다.
파이핑과 리디렉션을 결합해 명령줄의 진짜 힘 끌어내기
파이핑과 리디렉션을 함께 사용하면 복잡한 작업도 손쉽게 처리할 수 있습니다. 두 기능을 조합하는 법을 익히면, 타이핑을 최소화하면서 다양한 작업을 수행하는 강력한 명령어를 만들 수 있습니다.
다음 명령어를 예로 들어보겠습니다.
ls | grep ".txt" > text_files.txt
ls 명령어가 현재 디렉터리의 내용을 나열하고, 그 출력이 grep 명령어로 전달되어 텍스트 파일만 걸러집니다. 마지막으로 grep의 결과가 text_files.txt 파일로 리디렉션되어 저장됩니다.
이 간단하지만 강력한 예제가 보여주듯, 파이핑과 리디렉션의 한계는 오직 여러분의 상상력뿐입니다.
마무리
이 튜토리얼에서는 리눅스의 파이핑과 리디렉션의 기본기를 다루었습니다. 두 기능의 개념과 함께 실제 활용 예제도 함께 살펴보았습니다.
각각의 기능만으로도 강력하지만, 마지막 섹션에서 확인했듯이 두 기능을 명령어 안에서 조합하면 훨씬 더 강력한 결과를 얻을 수 있습니다.