리눅스에 대한 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.
https://reakwon.tistory.com/233
재지정(Redirection)
리눅스에서 프로그램은 보통 세 개의 파일 서술사를 열게 됩니다. 바로 표준 입력(standard input, STDIN), 표준 출력(standard output, STDOUT), 그리고 표준 에러(standard error, STDERR)가 되지요.
순서대로 파일 디스크립터(fild descriptor)는 0, 1, 2입니다.
리다이렉션(Redirection)이라고 하는 것은 이러한 서술자 중 하나 이상을 파일로 다시 지정하는 수단이라고 볼 수 있는데요. 어떻게 리다이렉션을 사용할까요?
1) program > file_name
>는 이해하기 쉽습니다. program에서 출력하는 것을 file_name이라는 파일에 기록하겠다는 것입니다. 더 잘 이해하기 위해서 저의 리눅스를 활용해보도록 하지요.
제 리눅스의 /tmp 디렉터리에는 다음과 같은 파일들이 있습니다.
무슨 파일들인지는 잘 모르겠네요.
[root@localhost tmp]# ls systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-ModemManager.service-OOhWCc systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-bolt.service-KuASd9 systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-chronyd.service-mPGGCi systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-colord.service-uTlHDZ systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-fwupd.service-mV4Wkl systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-rtkit-daemon.service-eaiBmp |
ls 명령을 치는 순간 화면에 보이는 파일들의 목록이 있죠? 이것은 표준 출력으로 표시한 것입니다. 쉽게 이해하기 위해서 모니터가 표준 출력이라고 보세요.
이제는 이것을 파일로 저장해보도록 합시다. 위의 꺽쇠를 이용하면 됩니다.
[root@localhost tmp]# ls > list_stdout [root@localhost tmp]# cat list_stdout list_stdout systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-ModemManager.service-OOhWCc systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-bolt.service-KuASd9 systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-chronyd.service-mPGGCi systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-colord.service-uTlHDZ systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-fwupd.service-mV4Wkl systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-rtkit-daemon.service-eaiBmp tracker-extract-files.0 |
그러면 list_stdout이 생겨날텐데 이것을 cat명령어로 실행해보면 파일의 내용을 볼 수 있습니다. 위의 ls 명령어의 결과와 같죠?
그렇다면 다음의 명령은 어떻게 출력이 될까요? 분명 위의 ls에는 aaa.txt라는 파일은 없었습니다. 과연 파일로 저장될까요?
[root@localhost tmp]# ls -l aaa.txt > list_aaa ls: cannot access 'aaa.txt': 그런 파일이나 디렉터리가 없습니다 [root@localhost tmp]# cat list_aaa |
list_aaa가 생겨나지 않았고 메시지가 출력이 되네요. 여기서 위의 메시지는 stderr로 출력된 에러 메시지입니다. stderr로 출력된 에러 메시지는 list_aaa의 파일로 저장이 되지 않네요.
그 이유는 기본적으로 ls -l aaa.txt > list_aaa는 ls -l aaa.txt 1> list_aaa와 같이 동작합니다. 여기서 숫자 1은 표줄 출력(stdout)을 의미하게 됩니다. 1이 파일 디스크립터라면 우리는 표준 에러는 다음과 같이 저장할 수 있겠군요.
아래의 결과를 보면 2(표준에러)가 리다이렉션되어 파일의 내용으로 전달되는 것을 알 수 있습니다.
[root@localhost tmp]# ls -l aaa.txt 2> list_aaa [root@localhost tmp]# cat list_aaa ls: cannot access 'aaa.txt': 그런 파일이나 디렉터리가 없습니다 |
2) program >> file_name
꺽쇠가 두개 연달아 있는 것은 파일의 끝에 내용을 덧붙이라는 것으로 여러분이 직접 실험해보시기 바랍니다.
3) program < file_name
여기서부터는 조금 헷갈릴 수 있으니 잘 들으세요. 아니, 보세요. file_name의 파일 내용을 program의 표준 입력으로 사용하겠다 라는 의미가 됩니다.
ls는 표준입력을 받지 않는다.
자, 프로그램에는 표준 입력으로 사용자의 입력을 받는 것이 있고 그렇지 않는 프로그램이 있습니다. 여기서 ls는 사용자의 입력을 표준입력으로 받을까요? 결론은 아닌데요.
아래의 내용으로 확인해보겠습니다.
우선 아까 없던 aaa.txt를 만들어볼텐데 aaa.txt에는 aaa라는 문자를 기록하도록 하지요. 그리고 다시 echo를 사용해 bbb라는 내용을 갖는 aaa파일을 만들어봅시다.
[root@localhost tmp]# echo aaa > aaa.txt [root@localhost tmp]# ls aaa.txt aaa.txt [root@localhost tmp]# echo bbb > aaa [root@localhost tmp]# ls aaa aaa |
(echo는 그 다음의 입력을 표준 출력으로 출력하는데 아까 배운 >을 통해서 파일로 저장했습니다. )
이제 ls에 aaa.txt의 내용을 표준입력으로 받아보도록 하겠습니다.
[root@localhost tmp]# ls < aaa.txt aaa aaa.txt systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-ModemManager.service-OOhWCc systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-bolt.service-KuASd9 systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-chronyd.service-mPGGCi systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-colord.service-uTlHDZ systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-fwupd.service-mV4Wkl systemd-private-b2dd06a5829f42f5b5f2e122f17b9afb-rtkit-daemon.service-eaiBmp tracker-extract-files.0 |
뭐 얼핏보면 뭔가 출력이 됐는데 우리가 원하는 결과는 aaa.txt의 내용은 bbb가 ls의 입력으로 들어가서 ls aaa라는 명령어가 수행되어야하는 것입니다. 근데 제가 전달하는 입력을 씹고 현재 디렉터리의 파일 내용을 출력하고 있죠. 이것은 ls의 기본 동작입니다.
ls는 이 처럼 표준 입력을 받지 않습니다. 대신 argv라고하는 argument vector를 통해서 사용자 입력을 받고 있는 셈입니다.
표준입력을 받는 명령어는 무엇이 있을까요?
대표적으로 cat, grep 등이 있습니다.
cat의 기본 동작
cat의 기본동작(아무런 옵션을 주지 않을때의 동작)은 입력받은 거 그대로 출력하는 기능입니다. 그 입력은 표준입력으로 받습니다.
표준 입력으로 받으니 이것을 파일의 내용을 입력으로 줘보겠습니다.
[root@localhost tmp]# echo Hello > hello.txt [root@localhost tmp]# cat < hello.txt Hello |
cat명령어는 argv로 파일 이름을 인자로 받을 수 있도록 프로그램이 되어있는데, 결과는 위와 같습니다.
grep의 기본 동작
grep은 기본적으로 바로 뒤에 인자가 포함된 문자열이 입력이 되면 그 문자열을 다시 출력해줍니다. 아래의 결과를 보면 알 수 있는데 이 grep은 표준 입력으로 입력을 받습니다.
[root@localhost tmp]# grep reak AAA BBB rea rreak rreak rreakk rreakk mmsmsms |
자, 여기서 눈 여겨 봐야할 것은 grep은 굵은 글씨인 rreak, rreakk만 출력하였습니다. 왜냐면 인자로 받은 reak라는 문자열이 포함되있기 때문이죠.
표준 입력으로 받으니 우리는 파일을 입력으로 리다이렉션을 쓸 수 있겠군요. 위의 입력했던 내용을 그대로 vi 편집기로 저장합니다.
[root@localhost tmp]# vi grep_test [root@localhost tmp]# grep reak < grep_test rreak rreakk |
vi 편집기 내용
AAA BBB rea rreak rreakk mmsmsms |
표준 입력으로 받은 결과와 동일함을 알 수 있네요.
리다이렉션을 통한 Copy
리다이렉션을 통해서 파일을 복사할 수도 있는데요. 아래를 보도록 합시다. echo로 file을 생성한 후에 cat의 입력으로 file의 내용을 받습니다. 그 후에 cat은 표준 출력으로 file의 내용을 출력하는데 다시 >로 표준 출력의 내용을 file_copied라는 파일에 저장합니다. 결국은 복사를 수행한 것과 같게 됩니다.
[root@localhost tmp]# echo hello > file [root@localhost tmp]# cat < file > file_copied [root@localhost tmp]# cat file_copied hello |
파이프( | )
파이프라는 것은 program1의 표준 출력을 program2의 표준입력으로 입력받습니다. 명령어의 결과를 다시 어떤 명령어의 입력으로 받아야할때 사용되며 리눅스에서 매우 흔히 쓰입니다. 형식은 아래와 같습니다.
program1 | program2
파이프라는 것은 program1의 표준 출력을 program2의 표준입력으로 입력받습니다. 리눅스에서 매우 흔히 쓰이는데요. 가장 빈번하게 사용하는 grep과 연관시켜서 사용해봅시다.
우선 제 리눅스에서 /bin으로 이동했습니다. 그리고 ls -l 명령을 보면 무수히 많은 파일들이 보이는데 그 중에서 zip이라는 문자열을 포함한 것을 확인해보고 싶습니다.
그렇다면 ls -l로 우선 표준 출력을 하고 이 표준 출력된 내용을 zip이라는 인자를 전달받는 grep에게 표준 입력으로 전달시키면 되겠죠?
답은 간단합니다. 아래의 명령을 실행시켜보세요.
[root@localhost bin]# ls -l | grep zip lrwxrwxrwx. 1 root root 5 5월 10 2019 bunzip2 -> bzip2 lrwxrwxrwx. 1 root root 5 5월 10 2019 bzcat -> bzip2 -rwxr-xr-x. 1 root root 38472 5월 10 2019 bzip2 -rwxr-xr-x. 1 root root 17560 5월 10 2019 bzip2recover -rwxr-xr-x. 1 root root 40256 5월 10 2019 funzip -rwxr-xr-x. 1 root root 3447 5월 10 2019 gpg-zip -rwxr-xr-x. 1 root root 2345 11월 8 2019 gunzip -rwxr-xr-x. 1 root root 170544 11월 8 2019 gzip lrwxrwxrwx. 1 root root 6 5월 11 2019 mzip -> mtools -rwxr-xr-x. 1 root root 5656 5월 13 2019 preunzip -rwxr-xr-x. 1 root root 5656 5월 13 2019 prezip -rwxr-xr-x. 1 root root 13352 5월 13 2019 prezip-bin -rwxr-xr-x. 2 root root 210408 5월 10 2019 unzip -rwxr-xr-x. 1 root root 105064 5월 10 2019 unzipsfx -rwxr-xr-x. 1 root root 234496 5월 11 2019 zip -rwxr-xr-x. 1 root root 105376 5월 11 2019 zipcloak -rwxr-xr-x. 1 root root 2953 10월 10 2008 zipgrep -rwxr-xr-x. 2 root root 210408 5월 10 2019 zipinfo -rwxr-xr-x. 1 root root 100104 5월 11 2019 zipnote -rwxr-xr-x. 1 root root 100112 5월 11 2019 zipsplit |
굳이 그림으로 표현하면 아래와 같이 실행됩니다.
이렇게 리다이렉션과 파이프에 대해서 알아보았습니다.
궁금하신 점은 댓글로 달아주세요.
'컴퓨터 > 운영체제(주로 리눅스)' 카테고리의 다른 글
[리눅스] 데몬 기초 : 개념과 구현 방법 (0) | 2020.12.19 |
---|---|
[리눅스] 다중입출력 - select개념과 설명과 예제 (1) | 2020.11.26 |
[리눅스] 파일 속성 변경 fcntl 사용법과 예제 (0) | 2020.06.28 |
[리눅스] 디스크 관련 명령어 df, du 명령어 사용법 (0) | 2020.06.28 |
[리눅스] getopt 실행 명령 인자(명령어 옵션) 파싱하기 (0) | 2020.06.25 |