여러 "사람"에 대해 작동하는 스크립트를 실행하고 각 사람에 대한 출력 및 오류 파일을 생성합니다. 이것을 이렇게 표현해보자:
output_alice.txt
error_alice.txt
output_bob.txt
error_bob.txt
.
.
.
error_<name>.txt
스크립트가 오류로 종료된 "사람"을 빠르게 식별할 수 있는 방법으로 모든 파일에서 오류( )를 검색하고 콘텐츠가 기록된 파일(비어 있는 파일이 아님)을 에코하는 명령을 원합니다 . 찾을 수 있는 단축키가 있나요? 나는 grep을 사용하여 문자열(예: )로 이 작업을 수행하는 방법을 알고 있지만 grep -r <substring> .
거기에 아무것도 있는지 확인하는 방법은 모릅니다.
답변1
bash는 그렇지 않습니다.단말기, 그것은 많은 것 중 하나입니다껍데기, 이는 명령 실행을 전문으로 하는 특정 프로그래밍 언어에 대한 통역사입니다. 대부분의 애플리케이션과 마찬가지로 입력/출력을 터미널 장치나 다른 유형의 파일에 연결할 수 있습니다.
bash 및 대부분의 다른 Unix 쉘 언어에서 현재 작업 디렉토리에 l
명명된 행이 하나 이상 포함된 파일을 나열하려면 다음을 수행할 수 있습니다.error_anything.txt
grep -l '^' error_*.txt
^
주제의 시작 부분과 일치하는 정규 표현식은 어디에 있습니까?주제파일의 각 줄은 입니다 grep
.
비어 있지 않은 텍스트 줄이 하나 이상 있는 사람의 경우:
grep -l . error_*.txt
여기서 .
단일 문자와 일치합니다. 로케일과 다른 문자 맵 인코딩을 사용하는 파일은 해당 내용을 텍스트로 디코딩할 수 없는 경우 비어 있지 않은 줄과 일치하지 않을 수 있습니다.
또한 모든 grep
구현이 종료되지 않은 줄이 하나만 포함된 파일을 보고하는 것은 아닙니다(의 출력에 표시된 것처럼 하나는 줄 구분 기호가 누락됨 printf invalid-text-as-missing-the-last-newline
).
또 다른 방법은 최소 1바이트를 포함하는 파일을 찾는 것입니다.
find -L . ! -name . -prune -name 'error_*.txt' -type f -size +0c
이는 해당 유형이 아닌 파일을 무시하는 이점도 있습니다.정기적인(예: 디렉토리, 소켓...)
또는 zsh 쉘을 사용하십시오.
print -rC1 -- error_*.txt(N-.L+0)
기호 링크의 경우 동작은 대상의 크기와 유형을 고려하여 ullglob 의 동작과 동일합니다(ullglob의 경우 -
일치하는 파일이 없으면 오류가 보고되지 않습니다).-L
.
-type f
L+0
-size +0c
N
N
이는 접두사를 포함하지 않는다는 장점이 있으며 ./
사용자 이름을 로케일의 텍스트로 디코딩할 수 없는 경우에도 작동하며 (어휘적으로) 정렬된 목록을 제공합니다.
r
이를 확장하여 사용자 이름(첫 번째 이름 뒤의 파일 oot 이름 부분 _
)만 인쇄할 수 있습니다.
{}{ print -rC1 -- ${@#*_}; } error_*.txt(N-.L+0:r)
error
명령을 실행한 이후 수정된 파일을 나열하려면 -newer
명령을 실행하기 전에 편집된 파일 의 조건자를 사용하고 find
비교할 수 있습니다.touch
touch .before
my-command-that-may-write-to-error-files
find -L . ! -name . -prune -name 'error_*.txt' -type f -size +0c -newer .before
find
zsh에서는 명령을 다음으로 바꿀 수 있습니다 .
print -rC1 -- error_*.txt(N-.L+0e['[[ $REPLY -nt .before ]]'])
일부 구현의 경우 로 find
바꿀 수 있지만 깊이 0()의 파일은 다른 기준과 일치하지 않기 때문에 여기서도 작동합니다 (일치하지도 않고 일치하지도 않음 ).! -name . -prune
-mindepth 1 -maxdepth 1
-maxdepth 1
.
-name 'error_*.txt'
-type f
date
and의 GNU 구현 (술어를 도입한 구현 find
이기도 함 )을 사용하면 다음을 수행하여 이 파일 생성을 피할 수 있습니다.find
-maxdepth
.before
before=$(date +'@%s.%N')
my-command-that-may-write-to-error-files
find -L . -maxdepth 1 -name 'error_*.txt' -type f -size +0c -newermt "$before"
를 사용할 때 또는 ( 뒤에 ) 로 zsh
바꿀 수 있습니다 . 다시 호출을 피할 수 있습니다.before=$(date +'@%s.%N')
print -Pv before '@%D{%s.%N}'
before=${(%):-@%{%s.%N}D}
before=@$EPOCHREALTIME
zmodload zsh/datetime
find
글로벌 예선, 심지어 임시 변수에 대해 익명 함수를 다시 사용하기도 하지만 이는 매우 복잡해집니다.
zmodload zsh/stat
zmodload zsh/datetime
() {
my-command-that-may-write-to-error-files
print -rC1 error_*.txt(N-.L+0e['
stat -F %s.%N -A2 +mtime -- $REPLY && (( $2 > $1 )) '])
} $EPOCHREALTIME
적어도 Linux에서는 시스템과 파일 시스템이 나노초 정밀도를 지원하지만 세분성은 훨씬 더 작습니다. 초기 호출 date
이나 참조 보다 이전 값을 수정할 때 수정 시간이 설정되어 있으므로 $EPOCHREALTIME
실행하는 데 100분의 1초도 걸리지 않는 명령에는 이러한 방법이 작동하지 않을 수도 있습니다. 1초를 제거 N
하고 이를 또는 >
로 바꾸는 것이 더 나은 접근 방식일 수 있습니다 ( 구현에서 지원하는 경우 가능성 없음).>=
-newer
! -older
find
답변2
GNU는 find
빈 파일을 나열하기 위해 POSIX가 아닌 옵션을 제공합니다. 테스트를 무효화하면 됩니다.
find /path/to/dir -type f -name 'error_*.txt' ! -empty
~을 위한아니요-maxdepth 1
검색할 경로 뒤에 하위 디렉터리를 추가합니다.
POSIX에서는 find
파일 크기 확인이 0
가능합니다 .
find /path/to/dir -type f -name 'error_*.txt' ! -size 0
답변3
grep for 는 .
모든 문자를 의미합니다. 빈 파일에는 문자가 없으므로 검색 시 .
비어 있지 않은 파일이 표시됩니다. 예를 들어:
$ touch empty1 empty2 empty3
$ echo "not empty!" > non_empty
$ ls -l
total 4
-rw-r--r-- 1 terdon terdon 0 Aug 11 13:13 empty1
-rw-r--r-- 1 terdon terdon 0 Aug 11 13:13 empty2
-rw-r--r-- 1 terdon terdon 0 Aug 11 13:13 empty3
-rw-r--r-- 1 terdon terdon 11 Aug 11 13:13 non_empty
이제 우리는 다음을 grep합니다.
$ grep -- . ./*
non_empty:not empty!
그리고 이름을 알아보세요.
$ grep -l -- . ./*
non_empty
grep .
빈 줄(하나 이상의 문자)이 없는 파일은 찾을 수 없습니다 \n
. 이를 위해서는 grep '^'
제안된 대로 사용해야 합니다.스티븐의 대답.
답변4
GNU sed 전용입니다. 다음 명령의 대안처럼 grep
:
sed -sn 1F error_*.txt
! F
매뉴얼 페이지에서 명령을 발견하지 못했지만 작동합니다. 특히 비어 있지 않은 파일의 첫 번째 줄에 파일 이름을 삽입합니다.sed -i 1F *