많은 디렉터리에서 grep을 사용하지만 모든 하위 디렉터리가 아닌 각 디렉터리의 특정 하위 디렉터리만 찾습니다.

많은 디렉터리에서 grep을 사용하지만 모든 하위 디렉터리가 아닌 각 디렉터리의 특정 하위 디렉터리만 찾습니다.

내 상황:

dir1 
  subdir1
      FooFile
  subdir2

dir2 
  subdir1
      FooFile
  subdir2

따라서 cd dir1, 나는 쉽게 다음과 같은 작업을 수행 find . | xargs grep "Foo"하여 Foo.

문제는 하위 디렉터리와 파일이 너무 많아서 검색하는 데 시간이 오래 걸린다는 것입니다. 각 홈 디렉터리로 재귀적으로 이동한 다음 구체적으로 하위 디렉터리(subdir1)로 이동한 다음 grep으로 이동하고 싶습니다.

Foo모든 디렉토리에 포함된 모든 파일의 이름을 나열하는 가장 좋은 방법은 무엇입니까? 이름이 다른 각 디렉터리의 경우 subdir1항상 한 수준 아래에 있으며 dir1항상 subdir1정확하게 이름이 지정됩니다.

답변1

무엇에 대해

grep "foo" */subdir1/*  */subdir1/.*

? (현재 문제에 따르면 이것은 계산서에 맞는 것 같습니다. 쉘이 전체 목록을 grep에 공급할 수 없을 정도로 "subdir1" 하위 디렉토리가 너무 많지 않는 한.

파일에 "foo"가 나타나는지 확인하려면 -q를 추가하고 0으로 종료되는지 테스트하면 됩니다.

또한 재귀 grep을 수행하고 필요하지 않은 것을 삭제할 수도 있습니다(많은 I/O이지만 간단함).

grep -r "foo" . | grep "^\./[^/][^/]*/subdir1/[^/][^/]*:"

(아래 참고 참조: 여기서는 이름에 ":"가 포함되어 있고 파일에 foo가 포함되어 있어도 subdir1에서 파일 이름을 찾은 것처럼 작동합니다. 그러나 다음과 같이 이름에 개행 문자가 있는 파일이 누락될 수 있습니다. 두 번째 grep에서는 첫 번째 "./firstleveldir/" 이름이 표시되지 않으므로 두 번째 grep에서는 이를 무시합니다...)

답변2

보고 싶다면존재하다그리고 아래모든 (하위)디렉토리는 subdir1 위에서 한 수준 아래로 이름이 지정됩니다.

find */subdir1 …

아래와 같은 서류를 찾고 계시다면이름포함되어 있습니다 Foo. 할 수 있습니다.

find */subdir1 -type f -name "*Foo*" -print

아니면 이렇게 할 수도 있어요

find */subdir1 -type f -print | grep "Foo"

하지만 여기에는 모든 파일이 포함됩니다.디렉토리에 이름에는 및 Foo와 같은 문자열이 포함되어 있습니다 .dir42/subdir1/Foods_I_Like/pizzadir42/subdir1/Foods_I_Like/chicken

당신이 찾고 있다면파일에 다음이 포함됨 Foo (즉, 누구의콘텐츠포함 Foo), 당신은 할 수 있습니다

find */subdir1 -type f -print | xargs grep "Foo"

노트:

  • 이는 find다음의 요약(사용) 때문에 작동합니다.
    찾다[옵션][초기점...][표현하다]
    즉, 다음 find과 같이 여러 출처에서 한 번 호출할 수 있습니다.
    찾다   디렉토리 1/하위 디렉토리 1 디렉토리 2/하위 디렉토리 1 [표현하다]
  • 이는 이름에 공백이 있는 파일 및 디렉터리에 잘 작동합니다.
  • 파일을 찾고 계시다면또는 디렉토리해당 이름은 해당 명령에 포함되거나 생략됩니다 Foo.-type f
  • 물론 인용해야 하며 "*Foo*", 인용할 수는 없습니다 */subdir1. 인용은 "Foo"선택 사항입니다. 문제가 되지는 않지만 특수 문자가 포함되지 않은 단어는 인용할 필요가 없습니다.
  • -print이는 기본 작업이므로 생략할 수 있습니다 .

답변3

다음과 같은 스크립트를 사용하여 이 작업을 수행할 수 있습니다.

#!/bin/sh
find . -type d | while IFS= read -r pathname
do
    for name in "$pathname"/subdir1/*Foo*
    do
        [ -f "$name" ] && echo "$name"
    done
done

경로 이름의 줄 바꿈에 대한 일반적인 경고입니다. 다음 트리로 테스트해 보세요.

./dir2
./dir2/subdir1
./dir2/subdir1/FooFile
./dir2/subdir2
./subdir1
./subdir1/FooFile
./dir spacew
./dir spacew/subdir1
./dir spacew/subdir1/FooFile
./dir spacew/subdir2
./dir1
./dir1/subdir1
./dir1/subdir1/FooFile

제작된 대본

./subdir1/FooFile
./dir2/subdir1/FooFile
./dir spacew/subdir1/FooFile
./dir1/subdir1/FooFile

의 사용과 관련하여 질문이 모호합니다 (작성된 대로 쉘 와일드카드 대신 정규식을 사용할 수 있다는 점을 제외하면 grep와 차이가 없습니다 ). echo또는 다음을 grep직접 사용할 수도 있습니다.

#!/bin/sh
find . -type f -name '*Foo*' | grep -E 'subdir1/Foo[^/]*$' | while IFS= read -r pathname
do
    echo "$pathname"
done

추가 자료:

관련 정보