man
이 옵션에 대한 페이지 설명 grep
은 다음과 같습니다 -d ACTION
.
입력 파일이 디렉터리인 경우
ACTION
이를 처리하는 데 사용합니다. 기본적으로ACTION
is 는read
일반 파일처럼 디렉터리를 읽습니다. [...]
bar
직관적으로 이것은 디렉토리가 (ping 목적을 위해 ) 내가 입력할 때 나타나는 것과 grep
거의 동일한 내용을 포함하는 텍스트 파일과 동일하게 처리된다는 것을 의미할 것으로 예상합니다 . 즉 대략(변경 내용에 따라 다름) 일종의 상단 및 하단에 설명 정보 및/또는 메타데이터 표시), 예:vim
vim foo
"============================================================================
" Netrw Directory Listing (netrw v156)
" /home/chris-henry/bar
" Sorted by name
" Sort sequence: [\/]$,\<core\%(\.\d\+\)\=\>,\.h$,\.c$,\.cpp$,\~\=\*$,*,\.o$,\.obj$,\.info$,\.swp$,\.bak$,\~$
" Quick Help: <F1>:help -:go up dir D:delete R:rename s:sort-by x:special
" ==============================================================================
../
./
foobar/
baz/
qux
이 경우 grep -H foo bar
출력이 생성됩니다 .
bar: foobar/
대신 메시지를 제공합니다 grep: bar: Is a directory
. 왜 이런거야? 직관적인 결과를 얻을 수 있는 (상당히 간단한) 방법이 있습니까(이 간단한 검색뿐만 아니라 텍스트 파일, 바이너리 파일 및 디렉터리의 일부 또는 전부와 일치하는 grep foo *
위치 와 같은 검색도 가능)?*
예상 도착 시간(2021-07-22):허용된 답변에서 제안되고 주석에서 확인된 것처럼 이 자체는 실제로 내가 예상한 것과 정확히 일치합니다. 일반 파일과 마찬가지로 파일 설명자를 사용하여 () grep foo bar
에 대한 시스템 호출을 호출합니다 . read
이때 내용을 채우는 대신 오류 코드가 반환되고 적절한 진단 메시지가 인쇄된 후 다음 파일로 프로세스가 계속됩니다. 이는 오류 코드(때로는 그렇지 않음)를 반환하고 일반 파일이 되는 것과 같습니다. .ssize_t read(int fd, void *buf, size_t count)
bar
bar
read
*buf
bar
EISDIR
grep
read
EINTR
EINVAL
bar
내 기대와 현실의 차이는 Linux 버전의 동작에서 비롯됩니다(댓글에 따르면 대부분의 다른 최신 버전) read
. 즉, fd
디렉토리가 참조되면 자동으로 반환됩니다 EISDIR
.
예상 도착 시간 2(2021-07-23):이 질문에 대한 주요 동기는 설명된 직관적인 동작을 획득해야 하는 긴급한 필요성이 아닙니다(비록 저는 이것이 잠재적인 이차적 이점으로 관심이 있지만). 동기는 grep
출력을 기반으로 (GNU)가 매뉴얼 페이지의 주장과 모순되는 것처럼 보이는 방식으로 작동하는 이유를 이해하는 것입니다.
대답은 grep
실제로 매뉴얼 페이지에 명시된 대로 수행하고 있다는 것입니다. 그러나 시스템 호출의 (일반적인) 동작이 변경 read
되면결과대부분의 최신 시스템에서는 grep
(최신 구현의 동작에 익숙하지 않은 상태에서) 매뉴얼 페이지를 읽는 것만으로는 read
추론할 수 있는 것과 상당히 다릅니다 .
전반적으로 나는 이 일을 하지 않는 편이 낫겠지만 read
, 이 행동이 다음과 관련이 있는지 의심스럽습니다.그것은맨 페이지. 현재 상황을 고려하면 매뉴얼 페이지에 한두 줄을 추가하고 싶었지만 grep
그렇지 않습니다.잘못된사실, 그것은 단지 오해의 소지가 있습니다.
답변1
디렉토리에는 텍스트 형식의 본질적인 표현이 없습니다. 많은 Unix 변형에서는 프로그램이 일반 파일처럼 디렉터리에서 데이터를 읽을 수 있도록 허용하지만 콘텐츠 형식이 파일 시스템에 따라 다르기 때문에 이는 거의 유용하지 않습니다. Linux를 포함한 일부 최신 Unix 변형프로그램이 디렉터리를 일반 파일인 것처럼 읽는 것을 완전히 방지합니다..
예를 들어, 다음은 FreeBSD에서 일어나는 일입니다(이전 버전에서는 여전히 허용합니다. FreeBSD 13부터는 기본적으로 비활성화되어 있습니다). 다음 디렉터리는 다음과 같습니다 bar
.
$ grep -H foo bar
Binary file bar matches
$ grep -H --text foo bar
bar:�"!
.�
..�"!foobar�"!
baz�"!qux
예, 디렉터리 표현에 존재하는지 확신할 수 있지만 foo
파일 이름의 일부인지는 확신할 수 없습니다. 예를 들어(여전히 FreeBSD 시스템에 있음):
$ rmdir bar/foobar
$ grep -H --text foo bar
bar:�"!
..�"!foobar�"!
baz�"!foo
디렉토리를 삭제하면 파일 시스템에서 디렉토리가 제거되지만 디렉토리를 인코딩하는 디스크 구조에서 삭제된 항목의 이름은 지워지지 않습니다.
Vim에게 디렉토리를 열도록 요청하면 Vim은 디렉토리를 탐색하고(예를 들어 readdir
일반 기능을 사용하는 대신 특수 시스템 기능을 사용하여 read
) 결과를 보기 좋게 표시합니다.
Grep은 비슷한 것을 구현할 수 있지만 grep의 크기에 비해 많은 작업이 필요하고 파일 내용을 검색하는 grep의 핵심 목적에서 벗어나 구현이 만족스럽지 못한 절충안이 되어야 합니다. 많은 사람. 디렉터리의 텍스트 표현에는 파일 이름이나 일부 메타데이터만 포함되어 있습니까( grep "Jul 20" bar
7월 20일에 수정된 파일을 찾을 수 없는 이유)? 항목을 분리하는 방법(파일 이름에 줄 바꿈이 포함될 수 있으므로 줄 바꿈으로 분리된 경우 표현이 모호합니다. 널 바이트로 분리된 경우 출력은 유용할 뿐입니다 grep --null-data
)?
쉘 와일드카드 find
및 locate
.