문자열의 마지막 항목을 찾으려면 여러 로그 파일 (지난 24 시간 동안 생성 된 모든 파일을 모두 동일한 디렉토리에 유지)을 검색해야합니다. 이것은 내가 쓴 명령입니다.
find . -mtime 1 | grep fileprefix | xargs grep 'search string' | tail -1
그러나 이것은 하나의 파일에 대한 마지막 줄만 반환합니다. 모든 라인을 얻기 위해 이것을 조정하는 방법에 대한 제안?
문자열의 마지막 항목을 찾으려면 여러 로그 파일 (지난 24 시간 동안 생성 된 모든 파일을 모두 동일한 디렉토리에 유지)을 검색해야합니다. 이것은 내가 쓴 명령입니다.
find . -mtime 1 | grep fileprefix | xargs grep 'search string' | tail -1
그러나 이것은 하나의 파일에 대한 마지막 줄만 반환합니다. 모든 라인을 얻기 위해 이것을 조정하는 방법에 대한 제안?
답변:
GNU 기능을 가정 :
find . -mtime -1 -exec bash -c \
'for f; do tac "$f" | grep -m1 fileprefix; done' _ {} +
find
사용하여 파일에서 명령을 실행할 수 있습니다 -exec
. 와 bash -c
, 우리가 산란하고 bash
파일을 통해 루프에 의해 발견 쉘을 find
실행한다 tac .. | grep -m1 fileprefix
각
-d" "
cut과 함께 사용하십시오 . 작은 따옴표 대신 큰 따옴표
find
명령은 파일 접두사를 필터링 할 수 있습니다. 은 grep
그 필요하지 않아야합니다. 검색 문자열이이 답변에 표시되지 않는다는 것도 놀라운 일입니다.
모든 것이 단일 디렉토리에있는 경우 다음을 수행 할 수 있습니다.
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
tac
. 첫 번째 경기가 발견되는 즉시 종료됩니다. 방금 832M 텍스트 파일과 마지막 줄에서 찾은 패턴으로 테스트했습니다. grep -m 1 pattern file
도구 ~ 7 초 tac file | grep -m1 pattern
소요 0.009
.
find . ! -name . -prune -mtime 1 -name 'fileprefix*' \
-exec sed -se'/searchstring/h;$!d;x' {} +
... eparate files 옵션과 POSIX sed
를 지원하는 GNU 가 있는 경우 작동합니다 .-s
find
디렉토리를 읽으려고 시도해도 유용하지 않으므로 일반 파일로 범위를 좁 히면 파이프 또는 직렬 장치 파일에서 읽기가 중단되는 것을 피할 수 있기 때문에 ! -type d
또는 -type f
한정자를 추가해야 합니다.
논리는 매우 간단 sed
합니다. h
이전 공간을 일치하는 입력 행의 복사본으로 덮어 쓴 searchstring
다음 d
모든 입력 행의 출력에서 각 입력 파일의 마지막 행 을 생략합니다. 마지막 행에 도달하면 x
보류 및 패턴 공간이 변경되므로 searchstring
파일을 읽는 동안 발견 된 경우 마지막으로 발생한 항목이 출력되도록 자동 인쇄되고, 그렇지 않으면 빈 행을 씁니다. ( 원치 않는 경우 스크립트 /./!d
의 꼬리 부분에 추가하십시오 sed
) .
이것은 sed
약 65k 입력 파일마다 또는 ARG_MAX
한도에 관계없이 단일 호출 을 수행합니다 . 이것은 매우 성능이 뛰어난 솔루션이어야하며 매우 간단하게 구현됩니다.
최신 GNU가 주어지면 파일 이름을 원한다면 명령을 사용하여 파일 sed
을 별도의 줄에 작성 F
하거나 find
배치 -print
후 별도의 목록으로 인쇄 할 수 있습니다 +
.
어때요 :
find . -mtime -1 -name "fileprefix*" -exec sh -c \
'echo "$(grep 'search string' $1 | tail -n 1),$1"' _ {} \;
위의 내용은 각 파일에서 마지막으로 나타나는 검색 문자열과 쉼표 뒤에 각각의 파일 이름이 나오는 멋진 결과를 제공합니다 (에코 아래에서 ", $ 1"부분을 수정하여 포맷을 변경하거나 필요없는 경우 제거). 접두사가 "file"인 파일에서 '10'검색 문자열을 검색하는 샘플 출력은 다음과 같습니다.
[dmitry@localhost sourceDir]$ find . -mtime -1 -name "file*" -exec sh -c 'echo "$(grep '10' $1 | tail -n 1),$1"' _ {} \;
Another data 02 10,./file02.log
Some data 01 10,./file01.log
Yet another data 03 10,./file03.log
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
항상 파일 이름과 모든 일치의 LINENUMBER 모두를 인쇄하려면 옵션을, 다음은 파일 이름과 LINENUMBER하고, AWK에 파이프를에 의해 정렬하는 저장 배열에있는 각 파일 이름의 마지막 경기, 결국 인쇄 그것.
상당히 무차별 한 방법이지만 작동합니다.