현재 디렉터리의 하위 디렉터리에 끝에 개행 문자가 있을 수도 있고 없을 수도 있는 파일이 있습니다. 끝에 개행 문자가 없는 파일을 어떻게 찾을 수 있나요?
나는 이것을 시도했습니다 :
find . -name '*.styl' | while read file; do
awk 'END{print}' $file | grep -E '^$' > /dev/null || echo $file;
done
하지만 작동하지 않습니다. awk 'END{print}' $file
와 동일하게 빈 새 줄 앞에 줄을 인쇄합니다 tail -n 1 $file
.
답변1
명확히 하기 위해 LF(일명 \n
개행 문자) 문자는 다음 줄입니다.구분 기호, 이는 줄 구분 기호가 아닙니다. 개행 문자로 끝나지 않는 한 줄은 끝나지 않습니다. 포함된 파일은 a\nb
마지막 줄 뒤에 문자가 포함되어 있으므로 유효한 텍스트 파일이 아닙니다. 비어 있지 않은 줄이 하나만 포함된 파일의 경우 a
.a\n
따라서 하나 이상의 빈 줄로 끝나는 파일은 두 개의 줄 바꿈으로 끝나거나 하나의 줄 바꿈을 포함합니다.
만약에:
tail -c 2 file | od -An -vtc
출력 \n
또는 \n \n
파일에는 적어도 하나의 후행 빈 줄이 포함되어 있습니다. 아무것도 출력하지 않으면 빈 파일이고, 출력하면 <anything-but-\0> \n
비어 있지 않은 줄로 끝납니다. 그 외에는 텍스트 파일이 아닙니다.
이제 이것을 사용하여 빈 줄로 끝나는 파일을 찾으려면 파일의 마지막 2바이트만 읽기 때문에 작동합니다(특히 대용량 파일의 경우). 그러나 먼저 출력을 프로그래밍 방식으로 구문 분석하기가 쉽지 않습니다. 한 구현에서 다음 구현까지 일관성이 없으므로 각 파일에 대해 하나씩 od
실행해야 합니다 .tail
od
find . -type f -size +0 -exec gawk '
ENDFILE{if ($0 == "") print FILENAME}' {} +
(빈 줄로 끝나는 파일 찾기)는 가능한 한 적은 수의 명령을 실행하지만 이는 모든 파일의 전체 내용을 읽는다는 의미입니다.
이상적으로는 자체적으로 파일의 끝을 읽을 수 있는 셸이 필요합니다.
그리고 zsh
:
zmodload zsh/system
for f (**/*(D.L+0)) {
{
sysseek -w end -2
sysread
[[ $REPLY = $'\n' || $REPLY = $'\n\n' ]] && print -r -- $f
} < $f
}
답변2
gnu sed
및 유사한 쉘을 사용하십시오 zsh
(또는 bash
사용 shopt -s globstar
):
sed -ns '${/./F}' ./**/*.styl
각 파일의 마지막 줄이 비어 있지 않은지 확인하고 비어 있으면 파일 이름을 인쇄합니다.
반대 결과를 원한다면 (마지막 줄이 비어 있으면 파일 이름을 인쇄하십시오) 다음 /./
으로 바꾸십시오./^$/
답변3
적절하게 종료된 텍스트 파일은 빈 마지막 줄로 끝나고 두 개의 \n
.
그렇다면 우리의 기대값 tail -c2
은 와 같아야 합니다 $'\n\n'
.
불행히도 명령 확장은 후행 새 줄을 제거합니다. 몇 가지 조정이 필요합니다.
f=filename
nl='
'
t=$(tail -c2 $f; printf x) # capture the last two characters.
r="${nl}${nl}$" # regex for: "ends in two newlines".
[[ ${t%x} =~ $r ]] && echo "file $f ends in an empty line"
어떤 파일에 줄바꿈 문자가 없는지 확인하기 위해 약간 확장할 수도 있습니다.
nl='
'
nl=$'\n'
find . -type f -name '*.styl' | while read f; do
t=$(tail -c2 $f; printf x); r1="${nl}$"; r2="${nl}${r1}"
[[ ${t%x} =~ $r1 ]] || echo "file $f is missing a trailing newline"
[[ ${t%x} =~ $r2 ]] && echo "$f"
done
$'\r\n
필요한 경우 줄 바꿈을 이와 같이 변경할 수 있습니다.
이 경우에도 tail -c2
로 변경합니다 tail -c4
.