자신의 이름을 포함하는 텍스트 파일

자신의 이름을 포함하는 텍스트 파일

디렉터리와 모든 하위 디렉터리에서 자신의 이름이 포함된 모든 텍스트 파일을 찾아야 합니다. 어떻게 해야 하나요? (바람직하게는 awk 명령 없이)

답변1

이식성을 최대화하고 파일 이름에 공백이나 기타 문자가 포함될 수 있는 경우 및 IFS내부 따옴표를 처리하지 않는 시스템에서 작동하려면 다음을 사용하십시오.find{}find -exec결합하다그리고sh일반 매개변수 전달:

find DIRECTORY -type f -exec sh -c 'grep -lFe "$(basename "$1")" "$1"' sh {} ';'

find DIRECTORY -type f모든 일반 파일을 재귀적으로 열거합니다 DIRECTORY. -exec ... ';'찾은 각 파일에 대해 명령을 실행합니다. 핵심은 shto 명령을 통해 이루어집니다 {}. 여기서:

  • 다음 명령을 사용하여 표준 쉘을 실행하십시오.스크립트grep -lFe "$(basename "$1")" "$1"일치하는 각 파일에 대한 명령 문자열입니다. 여기서:
    • $1일치하는 파일( )의 기본 파일 이름을 찾으려면 다음 명령을 사용하십시오.명령 대체그리고기본 이름- 공백이나 와일드카드가 포함될 수 있는 경우를 설명하기 위해 명령 대체 및 변수가 인용됩니다.
    • grep이 기본 이름에 대한 일치 파일(여전히 " $1") 은 -l일치하는 파일의 이름만 인쇄하는 데 사용됩니다. "$1"공백이나 와일드카드 문자를 해결하려면 다시 인용하세요.
  • 그리고 두 개의 매개변수를 sh" sh" 및 에 전달합니다 {}. sh인라인 스크립트 $0(오류 보고를 위한 셸과 같은 실행 중인 프로그램의 이름)에 사용됩니다. 일치하는 파일 이름으로만 구성된 인수는 대체되므로 find스크립트 자체는 전체 파일 경로를 .{}sh$1

이는 모든 POSIX 호환 시스템에서 작동합니다. {}인용된 문자열 내에서 사용됨find -exec 구현에 따라 정의된 동작이 있음grep따라서 이식성이 없으며(GNU 및 대부분의 BSD가 이를 지원하지만) 파일 이름이 해석되기 때문에 위험합니다.쉘코드로.

임의의 파일 이름에는 IFS값을 알 수 없는 공백, 와일드카드 또는 입력 필드 구분 기호 변수가 포함될 수 있는 경우 항상 인용해야 합니다. 그렇지 않으면 여러 단어로 분할되어 프로그램이 예기치 않은 방식으로 작동하게 됩니다.


보다 효율적으로 find -execwith를 사용 +하면 가능한 한 적은 수의 셸을 실행할 수 있습니다.

find DIRECTORY -type f -exec sh -c 'for x in "$@" ; do grep -lFe "$(basename "$x")" "$x" ; done' sh {} '+'

이것은 여전히 ​​이식 가능하지만 각 실행에 대해 많은 파일 경로를 제공하므로 sh많은 셸을 시작하지 않습니다. 쉘 프로그램이 있습니다for반지모든 파일을 살펴봅니다. 자주 실행되는 작업이라면 ;" "로 명령을 종료하는 것보다 더 나은 옵션입니다.

답변2

find directoryname -type f -exec grep -l {} {} \;

이는 find순수 파일(예: 디렉토리, 장치, 심볼릭 링크 등 제외)을 검색하고 grep주어진 인수를 사용하여 발견된 각 파일을 실행하도록 지시합니다. -l일치하는 행이 아닌 파일 이름만 표시하도록 grep에 지시합니다. {}파일 이름을 나타내고 \;명령을 종료합니다.

물론 경로가 아니라 파일 이름 자체를 검색해야 한다는 뜻일 수도 있습니다. 이는 첫 번째 섹션에서 목차 섹션을 제거해야 함을 의미합니다 {}. 한 가지 해결책은 다음과 같습니다.

find directoryname -type f -exec sh -c 'grep -l $(basename {}) {}' \;

$( .. )이제 각 파일에 대해 매개변수 대체가 수행되어야 하므로 쉘이 시작됩니다. basename목차 섹션의 앞부분을 제거합니다.

작은따옴표가 필요합니다. 그렇지 않으면 $( .. ) 부분은 find를 통해 쉘을 시작할 때가 아니라 명령을 입력할 때 평가됩니다.

답변3

GNU 시스템에서는 다음을 수행할 수 있습니다.

find . -type f -printf '%f\0%p\0' | xargs -r0n2 grep -lFe

( -type f는 다음으로 제한됩니다.정기적인파일만. -xtype f일반 파일에 대한 심볼릭 링크도 고려하려면 )로 변경하세요.

답변4

이것은 나에게 효과적입니다.

find /path/ -type f -exec sh -c "grep -l \"\$(basename {})\" {}" \;

Explanation:
  • -type f: 파일만 찾기
  • sh -c: 각 파일에 대해 쉘을 실행합니다.
  • grep -l: 파일 이름만 표시
  • \$(basename {}): 기본 이름을 얻으려면 grep

관련 정보