특정 줄에 특정 문자열이 포함되지 않은 파일 나열

특정 줄에 특정 문자열이 포함되지 않은 파일 나열

확장자가 있는 모든 파일을 찾으려고 합니다..md

find . -type f -name "*.md"

그런 다음 두 번째 줄(줄 번호 = 2)에 다음으로 시작하고 끝나는 정확한 문자열이 포함되지 않은 파일을 필터링하고 싶습니다.author: Mr. Xab Ycd

두 번째 부분은 어떻게 해야 하나요? grep파일 전체를 검사하기 때문에 비효율적 입니다 .

답변1

find . -type f -name '*.md' -exec \
  sh -c 'sed 1d\;q "$1" | grep -qvx "author: Mr. Xab Ycd"' sh {} \; -print

위 명령에는 셸을 통해 혼동될 수 있는 파일 이름을 파이프할 필요 없이 모든 요구 사항이 포함되어 있습니다.

첫 번째 부분은 (거의) 귀하의 것에서 복사되었습니다. 라는 파일을 찾으십시오 *.md. 귀하의 경우에는 큰 따옴표를 "하드" 작은 따옴표로 변경했지만 이름이 지정된 파일을 찾으려면 *.$md큰 따옴표를 사용하십시오. , 변수 확장을 시도합니다 $md.

일치하는 파일 이름은 다른 테스트를 통과합니다 -exec. exec에 대한 인수는 .txt에 있는 특정 파일 이름에 대한 성공 또는 실패를 결정하는 작은 쉘 스크립트입니다 $1. 이 sed명령은 두 번째 줄만 인쇄합니다. 이를 수행하는 방법은 다양합니다. 예를 들면 다음과 같습니다.

  • sed -n '2{p;q;}'또는
  • sed '1d;q

첫 번째는 "기본적으로 줄이 인쇄되지 않지만 두 번째 줄이 보이면 인쇄한 다음 종료하세요"라고 말합니다. 두 번째는 "기본적으로 행을 인쇄하지만 첫 번째 행을 제거한 다음 (두 번째 행에서) 종료함을 의미합니다. 이 q명령은 종료하기 전에 현재 버퍼를 인쇄합니다.

텍스트 줄(있는 경우)은 grep으로 전달되어 전체 줄이 지정된 텍스트와 일치하는지(또는 일치하지 않는지) 확인합니다. 그렇다면아니요일치( -v)하면 전체 명령이 성공하고 find파일 이름이 인쇄됩니다.

답변2

find . -type f -name '*.md' -exec awk '
    FNR == 2 && $0 == "author: Mr. Xab Ycd" { exit 1 }
    FNR >  2 { exit 0 }' {} ';' -print

이는 최소 두 줄 길이의 파일을 필터링하는 데 사용되며 awk두 번째 줄은 정확히 언급한 문자열입니다. 두 번째 줄( FNR == 2)이 문자열과 정확히 동일한 경우 0이 아닌 종료 상태로 명시적으로 종료하여 이를 수행합니다. 두 번째 줄 이후의 줄에 도달하면 불필요한 내용의 구문 분석을 피하기 위해 종료 상태 0으로 종료됩니다.

종료 상태가 0인 경우(두 번째 줄에서 문자열을 찾을 수 없음) find명령은 계속해서 파일의 경로 이름을 인쇄합니다.-printawk

답변3

그리고 zsh:

by_Xab() {
  local line
  {
    IFS= read -r line &&
      IFS= read -r line &&
      [[ $line = "author: Mr. Xab Ycd" ]]
  } < ${1-$REPLY}
}
printf '%s\n' **/*.md(D.^+by_Xab)

파일당 최대 2줄을 읽고 명령을 실행하지 않으므로(모두 내장 명령임) find -exec파일당 하나 이상의 명령을 실행하는 것보다 훨씬 효율적입니다.

GNU를 사용하면 awk다음과 같은 작업을 수행할 수 있습니다.

STRING='author: Mr. Xab Ycd' find . -name '*.md' -type f -exec gawk '
  BEGINFILE {found = 0}
  FNR == 2  {found = $0 == ENVIRON["STRING"]; nextfile}
  ENDFILE   {if (!found) print FILENAME}' {} +

단일 호출을 실행 find하고 가능한 -exec ... {} +한 적은 호출 구문을 사용합니다.gawk

답변4

한 번에 하나의 파일을 제공하고 인쇄할 때 find책임은 다음과 같습니다 find.

find . -type f -exec perl -lne '$. == 2 && exit +/^author: Mr\. Xab Ycd$/' {} \; -print

여기에는 find여러 파일이 제공되며 인쇄 작업은 다음 명령으로 처리됩니다 perl.

find . -type f -size 0 -print -o -exec perl -lne '
   print $ARGV if $. == 2 && !/^author: Mr\. Xab Ycd$/;
   close(ARGV),next if $. == 2;
   print($ARGV),close(ARGV) if eof;
' {} +

이것폐쇄-영국폐쇄ARRGV필수 OTW 라인 카운터, 일명$.예정된 파일에 대해 초기화되지 않았습니다.

eof 절이 필요하며 길이가 1보다 큰 파일의 경우 두 번째 줄에 도달하거나 확인되지 않습니다.

관련 정보