![자신의 이름을 포함하는 텍스트 파일](https://linux55.com/image/58567/%EC%9E%90%EC%8B%A0%EC%9D%98%20%EC%9D%B4%EB%A6%84%EC%9D%84%20%ED%8F%AC%ED%95%A8%ED%95%98%EB%8A%94%20%ED%85%8D%EC%8A%A4%ED%8A%B8%20%ED%8C%8C%EC%9D%BC.png)
디렉터리와 모든 하위 디렉터리에서 자신의 이름이 포함된 모든 텍스트 파일을 찾아야 합니다. 어떻게 해야 하나요? (바람직하게는 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 ... ';'
찾은 각 파일에 대해 명령을 실행합니다. 핵심은 sh
to 명령을 통해 이루어집니다 {}
. 여기서:
- 다음 명령을 사용하여 표준 쉘을 실행하십시오.스크립트
grep -lFe "$(basename "$1")" "$1"
일치하는 각 파일에 대한 명령 문자열입니다. 여기서: - 그리고 두 개의 매개변수를
sh
"sh
" 및 에 전달합니다{}
.sh
인라인 스크립트$0
(오류 보고를 위한 셸과 같은 실행 중인 프로그램의 이름)에 사용됩니다. 일치하는 파일 이름으로만 구성된 인수는 대체되므로find
스크립트 자체는 전체 파일 경로를 .{}
sh
$1
이는 모든 POSIX 호환 시스템에서 작동합니다. {}
인용된 문자열 내에서 사용됨find -exec
구현에 따라 정의된 동작이 있음grep
따라서 이식성이 없으며(GNU 및 대부분의 BSD가 이를 지원하지만) 파일 이름이 해석되기 때문에 위험합니다.쉘코드로.
임의의 파일 이름에는 IFS
값을 알 수 없는 공백, 와일드카드 또는 입력 필드 구분 기호 변수가 포함될 수 있는 경우 항상 인용해야 합니다. 그렇지 않으면 여러 단어로 분할되어 프로그램이 예기치 않은 방식으로 작동하게 됩니다.
보다 효율적으로 find -exec
with를 사용 +
하면 가능한 한 적은 수의 셸을 실행할 수 있습니다.
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