디렉토리의 모든 파일에서 grep을 비재 귀적으로 사용하는 방법은 무엇입니까?


34

디렉토리의 모든 파일에서 텍스트 문자열을 검색하려고합니다 (하위 디렉토리 -r는 아닙니다 . 옵션이 그렇게한다는 것을 알고 있지만 원하는 것은 아닙니다).

  1. 달리는

    grep "string" /path/to/dir
    

    이 작업을 수행 할 수 있어야한다고 읽었습니다. 그러나 오류가 발생합니다.

    grep : dir : 디렉토리입니다

  2. 다음 grep으로 여러 파일에서 실행 을 시도했습니다 .

    grep "string" .bashrc .bash_aliases 완벽하게 작동합니다.

    grep "string" .bash* 의도 한대로 작동합니다.

    grep "string" * 나에게 오류를 준다 :

    grep: data: Is a directory
    grep: Desktop: Is a directory
    grep: Documents: Is a directory
    grep: Downloads: Is a directory
    ...
    

오류 만 인쇄되고 일치하는 줄을 얻지 못합니다. -s옵션을 사용해 보았지만 아무 소용이 없습니다.

그래서 내 질문 :

  1. grep(1)과 같이 디렉토리에서 사용할 수없는 이유는 무엇 입니까? 인터넷에서 많은 예를 보았습니다.
    편집 : "디렉토리에서 grep 사용"이라고 말하면 "하위 디렉토리를 제외한 해당 디렉토리의 모든 파일에서 검색"을 의미합니다. 나는 이것이 파일 대신 디렉토리를 전달할 때 grep 이하는 일이라고 생각합니다. 내가 틀렸어?

  2. grep(2)의 명령 동작을 설명하는 작업에 대해 설명 해주십시오 .
    편집 : 좀 더 구체적으로 설명하겠습니다. 와일드 카드를 사용하여 여러 파일을 지정하여 작업 하거나 검색 .bash*하지 않는 작업을 검색하는 이유는 무엇 입니까? *./*

  3. 하위 디렉토리가 아닌 디렉토리의 모든 파일을 어떻게 검색 할 수 grep있습니까?


또한 글 *로빙이라고 하는 쉘 확장 와일드 카드에 의존하고 있습니다. 글 로빙에는 .bashrc표준 과 같은 점으로 시작하는 파일 이름이 포함되지 않습니다 . 셸 옵션을 설정하여 이러한 파일을 포함시킬 수 있지만 수행중인 작업을 모르는 경우 약간 혼란 스러울 수 있습니다. 글 로빙 이해에 대한 유용한
Arronical

나는 왜 그런지 몰라,하지만 항상 숨겨진 파일을 globbing하고 항상 작동했습니다. 설정이나 무언가를 변경하지 않았습니다. (2)에서 지적했듯이 작동합니다 grep "string" .bash*.
John Red

죄송합니다. 마지막 예가 잘못되었습니다. 리눅스는 기술적으로 디렉토리를 다른 유형의 파일로 인식하기 때문에 숨겨진 파일에서도 검색 할 수 있으며 "디렉토리"를 억제 할 수 있습니다. 명령은 다음과 같습니다. grep "string" * .* 2>/dev/null또는grep -s "string" * .*
Terrance

답변:


40

Bash에서는 glob가 숨겨진 파일로 확장되지 않으므로 디렉토리의 모든 파일 을 검색 하려면 숨겨진 파일 .*과 non-hidden 을 지정해야합니다 *.

"디렉터리입니다"오류를 피하려면을 사용할 수 -d skip있지만 내 시스템에서도 grep: .gvfs: Permission denied 오류가 발생 하므로 -s모든 오류 메시지를 숨기는을 사용 하는 것이 좋습니다 .

그래서 당신이 찾고있는 명령은 다음과 같습니다

grep -s "string" * .*

다른 디렉토리에서 파일을 검색하는 경우 :

grep -s "string" /path/to/dir/{*,.*}

또 다른 옵션은 dotglob쉘 옵션 을 사용 하는 것입니다.이 옵션 을 사용하면 숨겨진 파일이 포함됩니다.

shopt -s dotglob
grep -s "string" *

다른 디렉토리에있는 파일의 경우 :

grep -s "string" /path/to/dir/*

† 누군가이 오류가 발생하지 않아야한다고 언급했습니다. 그들은 옳을지도 모른다-나는 약간의 독서를했지만 직접 머리 나 꼬리를 만들 수는 없었다.


사이의 공간에 대한 이유가 *.*?
Hashim

2
@Hashim는의 출력을 비교 echo * .*하고 echo *.*홈 디렉토리에 실행하고 차이가 명백해야한다. 그렇지 않으면 LMK와 설명하겠습니다.
wjandrea

재미있는, 그래서 echo *쇼가 아닌 숨김 파일 및 폴더, echo *.*쇼 숨겨지지 않은 파일, echo .*쇼 모든 파일 및 echo * .*프로그램의 모든 파일과 디렉토리. 그러나 후자의 경우 왜 둘 사이의 공간이 필요한가? 나에게 지저분한 느낌이 든다. 두 가지를 결합하여 동일한 결과를 얻을 수있는 방법이 없습니까? 아니면 왜 두 가지를 분리해야하는지 또는 * .*예외적 인 경우에 대한 구문 설명이 있습니까?
Hashim

1
@Hashim 나는 당신이 그 결론에 어떻게 왔는지 확신하지 못하므로 설명하겠습니다. 우선, 디렉토리는이 문맥에서 파일입니다. globs에서 *숨겨지지 않은 모든 파일 (즉 , 점으로 시작 하지 않는 파일 이름)을 나타냅니다 . .*(즉, 파일 이름 모든 숨겨진 파일을 나타냅니다 않는 점으로 시작) 및 *.*모든 비 숨겨진 파일을 나타냅니다 포함 된 점을. 에서 echo * .*서로 다른 globs와 있기 때문에, 두 globs와 별도이어야 하나, 숨겨진 하나를 숨겨. 내 대답에 썼 듯이 쉘 옵션 *을 켜면 숨겨진 파일을 포함 시킬 수 있습니다 dotglob.
wjandrea

1
*.*Windows (DOS)에서는 모든 파일을 나열하는 방법으로 일반적으로 사용 되지만 * nix에서는 점이있는 파일 만 포함하므로 * nix에서는 의미가 없습니다. 대신 *숨겨진 파일을 제외한 모든 파일을 나열하고 숨겨진 파일을 나열 하는 데 사용 .*합니다.
thomasrutter

10

-d skip추가 된 옵션 이 필요합니다 .

  1. Grep가 파일 내부를 검색 중입니다. 디렉토리 내부의 파일을 검색하려는 경우 말했듯이 재귀 적으로 검색 할 수 있습니다.

  2. 기본적으로 grep은 모든 파일을 읽고 디렉토리를 감지합니다. 기본적으로 -d옵션을 사용하여 디렉토리로 수행 할 작업을 정의하지 않았으므로 오류 출력이 발생합니다.

  3. 부모 디렉토리 내에서 검색하는 것은`grep -d skip "string"./*입니다.


grep에 대한 자세한 내용은를 참조하십시오 man grep.
anonymous2

(a) 편집 내용을 참조하십시오. (b) 사용 -d skip이 작동하지 않습니다. 기본적으로 동일합니다 -s. 또한 편집을 참조하십시오. (c) 아뇨, grep -d skip "string" ./*작동하지 않습니다.
John Red

7

오래된 타이머는 아마도 이것을 할 것입니다 :

find . -type f -print0 | xargs -0 grep "string"

3
왜 안돼 find . -type f -exec grep string {} +?
wchargin

5
당신도 원합니다 -maxdepth 1.
wchargin

@wchargin : 원하는 파일이 하나만있을 때 출력에 파일 이름을 원할 경우find . -type f -maxdepth 1 -exec grep string /dev/null {} +
Gregory Nisbet

1
@GregoryNisbet : -Hgrep에 전달하십시오 .
wchargin

2

Rephrasing-파일을 한 레벨의 서브 디렉토리 레벨에 배치하려고하지만 모든 서브 서브 디렉토리를 통해 재귀하지 않습니까?

grep forthis  *  */*

또는 현재 디렉토리에 파일을 원하지 않는 경우

grep forthis  */*

점으로 시작하는 디렉토리는 찾지 않습니다.

grep forthis  .*/*    */*   

그 일을해야합니다.

이 또한의 -maxdepth-mindepth제한은 사용할 매개 변수 find도 명령.


grep forthis */*현재 디렉토리와 하나의 디렉토리에서 파일을 모두 검색 하지 않습니까?
Hashim

@Hashim nope 대부분-cos */*는 하나의 슬래시와 만 일치합니다. a/b현재 디렉토리에 파일 이름이 있다면 `* / *는 그 파일 과 일치합니다.
Criggie

0

다음은 모든 오류를 건너 뛰지 않고 디렉토리를 건너 뛰는 예입니다.

grep --directories='skip' 'searchString' *
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.