쉘의 리디렉션 연산자를 사용하여 명령에 (존재하지 않는) 파일 이름을 제공하면 grep
쉘은 파일이 존재하지 않는다는 오류 메시지를 표시합니다. 그러나 명령에 인수로 동일한 파일 이름을 제공하면 grep
명령 자체가 해당 오류 메시지를 표시합니다 grep
. 왜 그런 겁니까?
여기에 내가 말하는 내용에 대한 데모가 있습니다. 명령을 실행할 때:
$ grep 'root' /etc/passw
다음과 같은 오류 메시지가 나타납니다.
grep: /etc/passw: No such file or directory
그러나 쉘 리디렉션을 통해 이런 방식으로 명령을 실행하면 다음과 같습니다.
$ grep 'root' < /etc/passw
대신 다음과 같은 오류 메시지가 나타납니다.
bash: /etc/passw: No such file or directory
입력 파일 이름을 지정하는 이 두 가지 방법의 차이점은 무엇이며, 이를 수행하도록 하는 데 어떤 의미가 있습니까?
답변1
첫 번째 명령( $ grep 'root' /etc/passw
)에서 인수를 제공하면 grep
이를 파일 이름으로 해석하여 검색합니다. 이( grep
)는 실패하므로 무슨 일이 일어났는지 알려줍니다. grep은 입력을 해석하고 이에 대해 작동합니다.
두 번째 명령( )에서는 grep 'root' < /etc/passw
쉘(여기: )을 표준 입력으로 bash
파이프합니다 . ( )이 찾지 못해서 이 사실을 여러분에게 전달합니다. 여기에서 bash는 사용자의 입력을 해석하고 이에 따라 조치를 취합니다./etc/passw
grep
bash
두 번째 명령은 개념적으로 표준 출력에 지정된 파일의 $ bash-cat /etc/passw | grep 'root'
where 작업을 인쇄하는 것과 동일합니다. 그런 다음 로 리디렉션됩니다 .bash-cat
cat
grep
$ bash-cat /etc/passw | grep 'root'
bash-cat: /etc/passw: 해당 파일이나 디렉터리가 없습니다
--
파이프에 대해 읽어보시면 이해하실 겁니다. (파이프라인: 소개)
답변2
이와 같은 I/O 리디렉션 연산자를 사용할 때 쉘 자체는 fd0에서 O_RDONLY로 명령 입력에 대한 표준 입력으로 파일을 엽니다. 명령은 읽을 수만 있지만 인수로 전달되면 명령 자체가 열린 파일을 처리합니다.
따라서 프로그램(예: awk
) 이 있고 <
리디렉션을 사용하여 파일 이름을 전달하고 열려 있는 파일을 인쇄하려고 하면 FILENAME
보고됩니다 -
(입력이 표준 입력임을 의미).
awk '{ print FILENAME }' --infile
--infile
awk '{ print FILENAME }' <--infile
-
또 다른 장점은 파일 이름이 하이픈으로 시작하면 쉘이 이를 자체적으로 처리하지만 이를 명령에 인수로 전달하면(예: grep
) 제공된 옵션이 유효하지 않다고 생각하기 때문에 불평할 것입니다.
grep root --infile
grep: unrecognized option '--infile'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
표준을 준수하는 표준 명령은 --
명령에 옵션 인수가 종료됨을 알려줌으로써 이 오류를 방지합니다. 파일에 대한 절대 또는 상대 경로를 제공하거나 ./--infle
명령을 사용하여 쉘이 파일을 열도록 할 수도 있습니다 command <--infile
.
참고: <inputfile command
is 와 동일한 변형을 사용하십시오 command <inputfile
.
또 다른 장점은 파일이 존재하지 않거나 쉘이 파일을 열 수 없으면 명령이 실행되지 않는다는 것입니다.
awk 'BEGIN{ print "ifrun" }' < non-existing_file
-bash: non-existing_file: No such file or directory
awk 'BEGIN{ print "ifrun" }' non-existing_file
ifrun