마지막으로 나타나는 문자열을 찾으려면 여러 로그 파일(모두 지난 24시간 내에 생성되고 모두 동일한 디렉터리에 저장됨)을 검색해야 합니다. 제가 쓴 명령은 다음과 같습니다.
find . -mtime 1 | grep fileprefix | xargs grep 'search string' | tail -1
그러나 이것은 파일의 마지막 줄만 반환합니다. 모든 라인을 얻기 위해 조정하는 방법에 대한 제안 사항이 있습니까?
답변1
모든 것이 하나의 디렉토리에 있으면 다음을 수행할 수 있습니다.
for file in *fileprefix*; do
grep 'search string' "$file" | tail -1
done
tac
대용량 파일인 경우 파일을 역순으로(마지막 줄부터) 인쇄한 다음 grep -m1
첫 번째 항목과 일치시켜 작업 속도를 높이는 것이 좋습니다 . 이렇게 하면 전체 파일을 읽을 필요가 없습니다.
for file in *fileprefix*; do
tac file | grep -m1 'search string'
done
두 가지 모두 일치하는 디렉터리가 없다고 가정합니다 fileprefix
. 오류가 있는 경우 무시할 수 있는 오류가 발생합니다. 이것이 문제인 경우 파일을 확인하십시오.
for file in *fileprefix*; do
[ -f "$file" ] && tac file | grep -m1 'search string'
done
파일 이름도 인쇄해야 하는 경우 -H
각 grep
호출에 해당 이름을 추가하세요. 또는 grep
지원하지 않는 경우 검색도 수행하도록 지시합니다 /dev/null
. 이는 출력을 변경하지 않지만 grep
여러 파일이 제공되므로 항상 각 히트의 파일 이름을 인쇄합니다.
for file in *fileprefix*; do
grep 'search string' "$file" /dev/null | tail -1
done
답변2
GNU 기능을 가정하면:
find . -mtime -1 -exec bash -c \
'for f; do tac "$f" | grep -m1 fileprefix; done' _ {} +
답변3
find . ! -name . -prune -mtime 1 -name 'fileprefix*' \
-exec sed -se'/searchstring/h;$!d;x' {} +
sed
... 독립형 파일 옵션과 POSIX 를 지원하는 GNU가 있는 경우 -s
작동합니다 find
.
그러나 디렉토리를 읽으려고 시도하는 것은 그리 유용하지 않으며 일반 파일로 범위를 좁히면 파이프나 직렬 장치 파일을 읽는 것을 방지할 수 있으므로 ! -type d
또는 한정자를 추가해야 합니다 .-type f
논리는 매우 간단합니다. 이전 공간을 일치하는 입력 줄의 복사본으로 덮어쓴 다음 sed
출력에서 각 입력 파일의 마지막 입력 줄을 제외한 모든 줄을 제거합니다. 마지막 줄에 도달하면 유지 및 패턴 공간이 변경되므로 파일을 읽는 동안 마지막 이벤트가 발견되면 자동으로 출력에 인쇄되고, 그렇지 않으면 빈 줄이 작성됩니다.h
searchstring
d
x
searchstring
/./!d
( 필요하지 않은 경우 스크립트 끝에 추가 )sed
.
sed
이는 약 65,000개의 입력 파일 또는 제한 ARG_MAX
에 관계없이 한 번의 호출을 수행합니다. 이는 성능이 매우 뛰어나고 구현이 매우 간단한 솔루션이어야 합니다.
최신 GNU에서 파일 이름 도 필요한 경우 sed
이 명령을 사용하여 별도의 줄 에 F
쓰거나 .find
-print
+
답변4
find . -mtime 1 -name 'fileprefix*' -exec grep -Hn 'search string' {} + |
sort -t: -k1,2 -n |
awk -F: '{key=$1 ; $1="" ; $2="" ; gsub(/^ /,"",$0); a[key]=$0}
END {for (key in a) { print key ":" a[key] }}'
이는 GNU grep
및 -H
옵션을 사용 -n
하여 일치하는 모든 파일 이름과 줄 번호를 항상 인쇄한 다음 파일 이름과 줄 번호별로 정렬하고 이를 awk로 파이프하여 각 파일 이름의 마지막 일치 항목을 배열에 저장하고 마지막으로 인쇄합니다.
이것은 다소 폭력적인 방법이지만 효과가 있습니다.