확장자가 있는 모든 파일을 찾으려고 합니다..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
명령은 계속해서 파일의 경로 이름을 인쇄합니다.-print
awk
답변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보다 큰 파일의 경우 두 번째 줄에 도달하거나 확인되지 않습니다.