find+grep이 일치할 때 파일 이름을 인쇄하는 방법 [중복]

find+grep이 일치할 때 파일 이름을 인쇄하는 방법 [중복]

다음 유용한 find 명령은 이름 태그의 값을 인쇄합니다.

find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \;

문제는 /tmp 아래에 여러 개의 xml 파일이 있는 경우 어떤 xml 파일에 이름 태그가 있는지 알 수 없다는 것입니다.

즉, 이 find 구문은 Name 값을 인쇄합니다.

하지만 xml 파일 이름은 없습니다.

grep이 일치할 때 파일 이름을 인쇄하는 방법을 제안하십시오.

(?<=<Name>).*(?=</Name>)

답변1

적절한 XML 파서(여기서 사용하는 것)를 사용하여 파일 이름 접미사가 at 이하인 모든 XML 파일에서 xmlstarlet모든 노드의 값을 추출하려면 다음을 수행합니다.Name.xml/tmp

find /tmp -type f -name '*.xml' -exec xmlstarlet sel -t -v '//Name' -nl {} + 

이것은 실제로아니요<Name>여는 태그와 해당하는 닫는 태그가 같은 줄에 있어야 하며 </Name>, 명령처럼 노드에 Name속성이 없어도 됩니다 grep.

xmlstarlet현재 처리 중인 파일 이름과 같은 추가 정보 출력을 사용하고 파일에 실제로 노드가 있는 경우에만 이 작업을 수행하려면 Name위 명령 xmlstarlet의 호출을 다음으로 바꾸세요 .find

xmlstarlet sel -t -i '//Name' -o '### ' -f -o ':' -nl -v '//Name' -nl

그러면 파일에 노드가 포함된 경우에만 접두사 ###와 접미사가 붙은 XML 파일의 경로 이름이 출력됩니다 . 그 다음에는 문서의 각 노드 값이 나옵니다 .:NameName


사용 grep:

grep명령줄에 여러 파일이 제공되면 일치 항목이 포함된 파일의 파일 이름이 항상 출력됩니다. 파일이 하나만 전달되면 파일 이름이 인쇄되지 않습니다.

실제 일치 항목과 함께 파일 이름이 항상 인쇄되도록 하려면 /dev/null다음을 grep에 추가 파일로 추가하세요.

find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} /dev/null \;

또는 통화 수를 잠재적으로 줄이려면 다음을 대신 grep사용하세요 find -exec grep ... {} +.

find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' /dev/null {} +

최소한 GNU, OpenBSD 및 FreeBSD는 파일이 하나만 제공되더라도 항상 파일 이름을 인쇄하는 플래그를 지원 grep합니다 . 당신이 그것을 사용하고 있기 때문에 아마도 GNU를 사용하고 있을 것입니다 .grep-Hgrep -Pgrep

답변2

grep에 "-H" 매개변수만 지정하면 grep이 처리할 파일이 하나만 있는 경우에도(귀하의 경우처럼) 파일 이름이 항상 인쇄됩니다.

답변3

이는 grepxml/html 파일(문서)을 구문 분석하는 데 적합한 도구가 아니며 강력하고 안정적인 솔루션을 제공하지 않습니다. "올바른" xml/html 파서를 사용하세요.xmlstarlet:

find /tmp -type f -name '*.xml' -exec xmlstarlet sel -t -m "//Name" -f -n {} \;
  • xmlstarlet sel -t -m "//Name" -f -n-f-입력 파일 이름은 입력 xml 문서가 ( ) XPATH 표현식과 일치하는 경우에만 인쇄됩니다 -m(옵션으로 확인)."//Name"

답변4

찾은 줄 다음에 파일 이름을 인쇄해도 괜찮다면 언제든지 "-print" 옵션을 찾을 수 있습니다:

find /tmp -type f -name '*.xml' -exec grep -o -P '(?<=<Name>).*(?=</Name>)' {} \; -print

관련 정보