파일 끝에 줄 바꿈을 추가하는 방법은 무엇입니까?


190

버전 제어 시스템을 사용하면 diff가 말할 때 소음에 짜증이납니다 No newline at end of file.

그래서 궁금해했습니다. 파일 끝에 줄 바꿈을 추가하여 해당 메시지를 제거하는 방법은 무엇입니까?



1
아래의 멋진 솔루션은 모든 파일을 재귀 적으로 삭제합니다. 의해 답변을 @Patrick Oscity
Qwerty


앞으로 텍스트 편집기에는 종종 사용자와 공동 작업자가 깨끗하게 유지하는 데 사용할 수있는 새로운 줄 바꿈이있는 옵션이 있습니다.
닉 T

답변:


44

프로젝트를 재귀 적으로 소독하려면이 oneliner를 사용하십시오.

git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done

설명:

  • git ls-files -z저장소에 파일을 나열합니다. 작업을 특정 파일 / 디렉토리로 제한하려는 경우에 유용한 추가 매개 변수로 선택적 패턴을 사용합니다. 다른 방법으로, find -print0 ...또는 유사한 프로그램을 사용 하여 영향을받는 파일을 나열 할 수 있습니다. 파일이 NUL구분 된 항목 인지 확인하십시오 .

  • while IFS= read -rd '' f; do ... done 공백 및 / 또는 줄 바꿈이 포함 된 파일 이름을 안전하게 처리하여 항목을 반복합니다.

  • tail -c1 < "$f" 파일에서 마지막 문자를 읽습니다.

  • read -r _ 후행 줄 바꿈이 없으면 0이 아닌 종료 상태로 종료합니다.

  • || echo >> "$f" 이전 명령의 종료 상태가 0이 아닌 경우 파일에 개행을 추가합니다.


파일의 하위 집합을 삭제하려는 경우 다음과 같이 수행 할 수도 있습니다.find -name \*.java | while read f; do tail -n1 $f | read -r _ || echo >> $f; done
Per Lundberg

@ StéphaneChazelas 좋은 제안은 이것을 내 대답에 통합하려고 시도합니다.
Patrick Oscity

@PerLundberg git ls-files버전 관리에서 추적되지 않는 파일을 편집하지 않아도 패턴을 전달할 수도 있습니다 .
Patrick Oscity

@ StéphaneChazelas를 추가하여 IFS= 분리자를 설정 해제하면 주변 공백을 유지하는 것이 좋습니다. null로 끝나는 항목은 이름에 개행 문자가있는 파일이나 디렉토리가있는 경우에만 관련이 있습니다. 작은 경고와 마찬가지로 POSIX sh 에서는 -d옵션을 read사용할 수 없습니다.
Patrick Oscity

예, 따라서 zsh / bash 's 입니다. 로 tail -n1 < "$f"시작하는 파일 이름의 문제를 피하기 위해 사용을 참조하십시오 -( tail -n1 -- "$f"라는 파일에는 작동하지 않음 -) 대답이 이제 zsh / bash와 관련되어 있음을 명확히 할 수 있습니다.
Stéphane Chazelas

202

여기 있습니다 :

sed -i -e '$a\' file

대안으로 OS X의 경우 sed:

sed -i '' -e '$a\' file

이렇게 하면 줄 바꿈으로 끝나지 않은 경우 에만\n 파일 끝에 추가 됩니다 . 따라서 두 번 실행하면 다른 줄 바꿈이 추가되지 않습니다.

$ cd "$(mktemp -d)"
$ printf foo > test.txt
$ sed -e '$a\' test.txt > test-with-eol.txt
$ diff test*
1c1
< foo
\ No newline at end of file
---
> foo
$ echo $?
1
$ sed -e '$a\' test-with-eol.txt > test-still-with-one-eol.txt
$ diff test-with-eol.txt test-still-with-one-eol.txt
$ echo $?
0

1
@jwd : 보낸 사람 man sed: $ Match the last line.그러나 우연히 만 작동합니다. 귀하의 솔루션도 작동합니다.
l0b0

1
귀하의 솔루션도 더 우아하며 테스트 및 커밋 했지만 어떻게 작동합니까? 경우 $마지막 줄 일치, 왜 문자열로 다른 줄 바꿈을 추가하지 않습니다 이미 줄 바꿈을 포함?
l0b0 2019

27
의 두 가지 의미가 $있습니다. 형식과 같은 정규 표현식 내부에는 /<regex>/일반적인 "줄 끝 일치"의미가 있습니다. 그렇지 않으면, 주소로 사용되는 sed는 특별한 "파일의 마지막 줄"을 의미합니다. sed는 기본적으로 개행을 출력에 추가하지 않기 때문에 기본적으로 코드가 작동합니다. "$ a \"코드는 "파일의 마지막 줄과 일치하고 아무 것도 추가하지 않습니다"라고 말합니다. 그러나 sed는 암시 적으로 줄 바꿈 $이없는 경우 처리하는 모든 줄 (예 :이 줄)에 줄 바꿈을 추가합니다 .
jwd

1
맨 페이지에 관하여 : 당신이 말하는 인용은 "주소"섹션에 있습니다. 그것을 안에 넣는 것은 /regex/다른 의미를 부여합니다. FreeBSD 맨 페이지는 좀 더 유익합니다. freebsd.org/cgi/man.cgi?query=sed
jwd

2
파일이 이미 줄 바꿈으로 끝나더라도 변경되지 않지만 파일을 다시 쓰고 타임 스탬프를 업데이트합니다. 그것은 중요하거나 중요하지 않을 수 있습니다.
Keith Thompson

39

보세요 :

$ echo -n foo > foo 
$ cat foo
foo$
$ echo "" >> foo
$ cat foo
foo

그래서 echo "" >> noeol-file트릭을 할해야합니다. (또는 이러한 파일을 식별 하고 수정하도록 요청 했습니까?)

edit 에서 ""from을 제거했습니다 echo "" >> foo(@yuyichao의 의견 참조) edit2""다시 추가 했습니다 ( 그러나 @Keith Thompson의 의견 참조)


4
""(적어도 bash에 대한) 필요하지 않으며 tail -1 | wc -l끝에 새 줄이없는 파일을 찾을 수 있습니다
yuyichao

5
@ yuyichao : ""bash에는 필요 echo하지 않지만 인수없이 호출 할 때 아무것도 인쇄하지 않는 구현을 보았습니다 (지금은 찾을 수있는 것은 없습니다). echo "" >> noeol-file아마 약간 더 강력 할 것입니다. printf "\n" >> noeol-file훨씬 더입니다.
Keith Thompson

2
@KeithThompson, csh's echo는 인수를 전달하지 않으면 아무것도 출력하지 않는 것으로 알려져 있습니다. 그러나 우리는 비 본쉘을 지원하는거야 다음, 우리는해야한다 echo ''대신 echo ""으로 echo ""OUPUT 것 ""<newline>으로 rc또는 es예를 들어.
Stéphane Chazelas

1
@ StéphaneChazelas : tcsh,와 달리 csh, 설정과 상관없이 인수없이 호출 할 때 줄 바꿈을 인쇄합니다 $echo_style.
키이스 톰슨

16

를 사용하는 다른 솔루션 ed. 이 솔루션은 마지막 줄에만 영향을 미칩니다 \n.

ed -s file <<< w

그것은 본질적으로 스크립트를 통해 편집하기 위해 파일을 여는 작업이며, 스크립트는 w파일을 디스크에 다시 쓰는 단일 명령입니다. ed(1)맨 페이지 에있는이 문장에 근거 합니다 :

한계
       (...)

       텍스트 (이진이 아닌) 파일이 줄 바꿈 문자로 끝나지 않으면
       그런 다음 ed는 읽거나 쓸 때 하나를 추가합니다. 이진의 경우
       ed는 읽기 / 쓰기에 개행을 추가하지 않습니다.

1
이것은 나를 위해 줄 바꿈을 추가하지 않습니다.
Olhovsky

4
나를 위해 작동합니다. 심지어 "Newline addeded"(아치 리눅스의 ed-1.10-1)도 출력합니다.
Stefan Majewsky

12

결석 한 최종 개행을 텍스트 파일에 추가하는 간단하고 이식 가능한 POSIX 호환 방법은 다음과 같습니다.

[ -n "$(tail -c1 file)" ] && echo >> file

이 방법은 전체 파일을 읽을 필요는 없습니다. 그것은 단순히 EOF를 추구하고 거기서부터 일할 수 있습니다.

이 방법은 또한 임시 파일 (예 : sed -i)을 만들 필요가 없으므로 하드 링크에는 영향을 미치지 않습니다.

echo는 명령 대체 결과가 비어 있지 않은 문자열 인 경우에만 파일에 개행을 추가합니다. 파일이 비어 있지 않고 마지막 바이트가 줄 바꿈이 아닌 경우에만 발생할 수 있습니다.

파일의 마지막 바이트가 줄 바꿈이면 tail은 해당 파일을 반환 한 다음 명령 대체에서 제거합니다. 결과는 빈 문자열입니다. -n 테스트가 실패하고 에코가 실행되지 않습니다.

파일이 비어 있으면 명령 대체 결과도 빈 문자열이며 echo가 다시 실행되지 않습니다. 빈 파일은 유효하지 않은 텍스트 파일이 아니거나 빈 줄이있는 비어 있지 않은 텍스트 파일과 동일하지 않기 때문에 바람직합니다.


1
yash파일의 마지막 문자가 멀티 바이트 문자 (예 : UTF-8 로케일)이거나 로케일이 C이고 파일의 마지막 바이트에 8 번째 비트 세트가있는 경우에는 작동하지 않습니다 . 다른 쉘 (zsh 제외)의 경우 파일이 NUL 바이트로 끝난 경우 줄 바꿈을 추가하지 않습니다 (다시 말해 줄 바꿈을 추가 한 후에도 입력이 텍스트가 아님).
Stéphane Chazelas


1
폴더와 하위 폴더의 모든 파일에 대해이 기능을 실행할 수 있습니까?
Qwerty

12

다음에 관계없이 줄 바꿈을 추가하십시오.

echo >> filename

다음은 파이썬을 사용하여 줄 바꿈을 추가하기 전에 줄 바꿈이 있는지 확인하는 방법입니다.

f=filename; python -c "import sys; sys.exit(open(\"$f\").read().endswith('\n'))" && echo >> $f

1
파이썬 시작 시간이 느리기 때문에 어떤 종류의 루프에서도 파이썬 버전을 사용하지 않습니다. 물론 원한다면 파이썬에서 루프를 수행 할 수 있습니다.
Kevin Cox

2
파이썬의 시작 시간은 0.03 초입니다. 정말로 문제가 있다고 생각합니까?
Alexander

3
시작 시간은 루프에서 파이썬을 호출하면 내가 루프하고 생각했다, 그 이유는 중요합니까 에서 파이썬. 그런 다음 시작 비용이 한 번만 발생합니다. 저에게는 스타트 업 비용의 절반이 전체 스 니핏 시간의 절반 이상인 것이므로 상당한 오버 헤드를 고려할 것입니다. (다시 말하지만, 관련성이없는 경우에만 적은 수의 파일을하는 경우)
케빈 콕스

2
echo ""보다 강력 해 보입니다 echo -n '\n'. 또는 당신은 사용할 수 있습니다printf '\n'
키이스 톰슨

2
이것은 나를 위해 잘 작동
다니엘 고메즈 리코

8

가장 빠른 해결책은 다음과 같습니다.

[ -n "$(tail -c1 file)" ] && printf '\n' >>file 

  1. 정말 빠릅니다.
    중간 크기의 파일 seq 99999999 >file에서는 몇 초가 걸립니다.
    다른 솔루션은 시간이 오래 걸립니다 :

    [ -n "$(tail -c1 file)" ] && printf '\n' >>file  0.013 sec
    vi -ecwq file                                    2.544 sec
    paste file 1<> file                             31.943 sec
    ed -s file <<< w                             1m  4.422 sec
    sed -i -e '$a\' file                         3m 20.931 sec
  2. ash, bash, lksh, mksh, ksh93, attsh 및 zsh에서 작동하지만 yash에서는 작동하지 않습니다.

  3. 개행을 추가 할 필요가 없으면 파일 타임 스탬프를 변경하지 않습니다.
    여기에 제시된 다른 모든 솔루션은 파일의 타임 스탬프를 변경합니다.
  4. 위의 모든 솔루션은 유효한 POSIX입니다.

yash (및 위에 나열된 다른 모든 셸)에 이식 가능한 솔루션이 필요한 경우 조금 더 복잡해질 수 있습니다.

f=file
if       [ "$(tail -c1 "$f"; echo x)" != "$(printf '\nx')" ]
then     printf '\n' >>"$f"
fi

7

파일의 마지막 바이트가 개행인지 테스트하는 가장 빠른 방법은 마지막 바이트 만 읽는 것입니다. 그것으로 할 수 있습니다 tail -c1 file. 그러나 셸에 따라 일반적으로 명령 확장 내에서 마지막 줄 바꿈을 제거하지 못하는 경우 (예 : 파일의 마지막 문자가 UTF- 인 경우 yash에서 바이트 값이 줄 바꿈인지 테스트하는 간단한 방법) 8 값.

파일의 마지막 바이트가 새로운 행인지 확인하는 올바른 POSIX 호환 모든 (합리적인) 쉘 방법은 xxd 또는 hexdump를 사용하는 것입니다.

tail -c1 file | xxd -u -p
tail -c1 file | hexdump -v -e '/1 "%02X"'

그런 다음 위의 출력을 비교하여 0A강력한 테스트를 제공합니다.
비어있는 파일에 새 줄을 추가하지 않는 것이 좋습니다. 물론
의 마지막 문자를 제공하지 못하는 파일 0A:

f=file
a=$(tail -c1 "$f" | hexdump -v -e '/1 "%02X"')
[ -s "$f" -a "$a" != "0A" ] && echo >> "$f"

짧고 달다. 마지막 바이트 (EOF로 검색)를 읽으므로 시간이 거의 걸리지 않습니다. 파일이 큰지는 중요하지 않습니다. 그런 다음 필요한 경우 1 바이트 만 추가하십시오.

임시 파일이 필요하거나 사용되지 않습니다. 하드 링크는 영향을받지 않습니다.

이 테스트를 두 번 실행 하면 다른 줄 바꿈이 추가 되지 않습니다 .


1
@ crw 유용한 정보를 추가한다고 생각합니다.
sorontar

2
POSIX 유틸리티 도 xxd아닙니다 hexdump. POSIX toolchest에서는 od -An -tx1바이트의 16 진수 값을 가져옵니다.
Stéphane Chazelas

@ StéphaneChazelas 답변으로 게시하십시오; 나는이 의견을 너무 많이 찾기 위해 여기에왔다 :)
kelvin


POSIX는 LF의 값이 0x0a임을 보증하지 않습니다. POSIX 시스템은 아직 (EBCDIC 기반 시스템이 아님) 여전히 요즘 드물지만 여전히 있습니다.
Stéphane Chazelas

4

파일을 마지막으로 편집 한 사용자의 편집기를 수정하는 것이 좋습니다. 당신이 파일을 편집 한 마지막 사람이라면-어떤 편집기를 사용하고 있습니까? 나는 textmate ..?


2
Vim이 문제의 편집자입니다. 그러나 일반적으로, 당신은 옳습니다, 나는
증상을

6
vim의 경우, 파일 끝에 새 줄을 추가 하지 않으 려면 vim을 가져 오려면 이진 파일 저장 춤을 수행해야합니다. 그 춤을 추지 마십시오. 또는 기존 파일을 간단히 수정하기 위해 vim에서 파일을 열고 저장하면 vim에서 누락 된 줄 바꿈을 '수정'합니다 (여러 파일에 대해 쉽게 스크립팅 가능)
AD7six

3
emacs파일의 끝에 줄 바꿈을 추가하지 마십시오.
enzotib 2012

2
의견 @ AD7six에 감사드립니다. 커밋을 할 때 원본 파일의 끝에 줄 바꿈이없는 방법에 대한 팬텀 보고서가 계속 표시됩니다. vim으로 파일을 편집하는 방법에 관계없이 줄 바꿈을 넣을 수는 없습니다. 그래서 그것은 단지 vim입니다.
Steven Lu

1
@enzotib : 나는 (setq require-final-newline 'ask).emacs
키이스 톰슨

3

파이프 라인을 처리 할 때 줄 바꿈을 빠르게 추가하려면 다음을 사용하십시오.

outputting_program | { cat ; echo ; }

POSIX 와도 호환됩니다.

물론 파일로 리디렉션 할 수 있습니다.


2
파이프 라인에서 이것을 사용할 수 있다는 사실이 도움이됩니다. 이렇게하면 헤더를 제외하고 CSV 파일의 행 수를 계산할 수 있습니다. 또한 줄 바꿈이나 캐리지 리턴으로 끝나지 않는 Windows 파일에서 정확한 줄 수를 얻습니다. cat file.csv | tr "\r" "\n" | { cat; echo; } | sed "/^[[:space:]]*$/d" | tail -n +2 | wc -l
Kyle Tolle

3

입력에 널이없는 경우 :

paste - <>infile >&0

... 파일 이름이없는 경우 항상 줄 바꿈을 파일의 꼬리 끝에 만 추가하면 충분합니다. 그리고 입력 파일을 올바르게 읽으려면 한 번만 입력하면됩니다.


stdin과 stdout이 동일한 열린 파일 설명을 공유하므로 파일 내에서 커서가 작동하므로 그렇게 작동하지 않습니다. paste infile 1<> infile대신에 필요 합니다.
Stéphane Chazelas

2

질문에 직접 대답하지는 않지만 다음은 줄 바꿈으로 끝나지 않는 파일을 감지하기 위해 작성한 관련 스크립트입니다. 매우 빠릅니다.

find . -type f | # sort |        # sort file names if you like
/usr/bin/perl -lne '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

perl 스크립트는 stdin에서 (선택적으로 정렬 된) 파일 이름 목록을 읽고 모든 파일에 대해 파일이 줄 바꿈으로 끝나는 지 여부를 판별하기 위해 마지막 바이트를 읽습니다. 각 파일의 전체 내용을 읽지 않기 때문에 매우 빠릅니다. 읽은 각 파일에 대해 한 줄씩 출력합니다. 어떤 종류의 오류가 발생하면 접두어 "error :", 파일이 비어있는 경우 "empty :"(개행으로 끝나지 않습니다!), "EOL :"( "끝 파일이 줄 바꿈으로 끝나는 경우 "line") 파일이 줄 바꿈으로 끝나지 않으면 "EOL 없음 :"입니다.

참고 :이 스크립트는 줄 바꿈이 포함 된 파일 이름을 처리하지 않습니다. GNU 또는 BSD 시스템을 사용하는 경우 다음과 같이 -print0을 찾아서 -z를 정렬하고 -0을 펄로 추가하여 가능한 모든 파일 이름을 처리 할 수 ​​있습니다.

find . -type f -print0 | sort -z |
/usr/bin/perl -ln0e '
   open FH, "<", $_ or do { print " error: $_"; next };
   $pos = sysseek FH, 0, 2;                     # seek to EOF
   if (!defined $pos)     { print " error: $_"; next }
   if ($pos == 0)         { print " empty: $_"; next }
   $pos = sysseek FH, -1, 1;                    # seek to last char
   if (!defined $pos)     { print " error: $_"; next }
   $cnt = sysread FH, $c, 1;
   if (!$cnt)             { print " error: $_"; next }
   if ($c eq "\n")        { print "   EOL: $_"; next }
   else                   { print "no EOL: $_"; next }
'

물론 출력에 줄 바꿈을 사용하여 파일 이름을 인코딩하는 방법을 생각해 내야합니다 (리더의 연습으로 남음).

원하는 경우 출력을 필터링하여 파일이없는 파일에 줄 바꾸기를 추가 할 수 있습니다.

 echo >> "$filename"

일부 버전의 셸 및 기타 유틸리티는 이러한 파일을 읽을 때 누락 된 최종 개행을 제대로 처리하지 않으므로 최종 개행이 없으면 스크립트에 버그가 발생할 수 있습니다.

내 경험상 최종 줄 바꿈이 부족한 것은 다양한 Windows 유틸리티를 사용하여 파일을 편집하기 때문입니다. 나는 파일을 편집 할 때 vim이 최종 줄 바꿈을 누락시키는 것을 보지 못했습니다.

마지막으로 파일 이름 입력을 반복하여 줄 바꿈으로 끝나지 않는 파일을 인쇄 할 수있는 훨씬 더 짧은 (그러나 더 느린) 스크립트가 있습니다.

/usr/bin/perl -ne 'print "$ARGV\n" if /.\z/' -- FILE1 FILE2 ...

1

vi/ vim/ ex편집자가 자동으로 추가 <EOL>파일이 이미 그것을 가지고 있지 않는 EOF에.

따라서 다음 중 하나를 시도하십시오.

vi -ecwq foo.txt

이는 다음과 같습니다.

ex -cwq foo.txt

테스트 :

$ printf foo > foo.txt && wc foo.txt
0 1 3 foo.txt
$ ex -scwq foo.txt && wc foo.txt
1 1 4 foo.txt

여러 파일 을 수정 하려면 다음을 확인하십시오. 많은 파일에 대해 '파일 끝에 줄 바꿈 없음'을 수정하는 방법은 무엇입니까? 그래서

이것이 왜 중요한가? POSIX 호환 파일을 유지합니다 .


0

허용 된 답변을 현재 디렉토리 (및 하위 디렉토리)의 모든 파일에 적용하려면 다음을 수행하십시오.

$ find . -type f -exec sed -i -e '$a\' {} \;

이것은 Linux (Ubuntu)에서 작동합니다. OS X에서는 아마 -i ''(unested) 를 사용해야 합니다.


4
find .파일을 포함하여 모든 파일 이 나열됩니다 .git. 제외 :find . -type f -not -path './.git/*' -exec sed -i -e '$a\' {} \;
friederbluemle

이 의견을 읽었을 때 그것을 읽었 으면 좋겠다. 오 잘
kstev

0

적어도 GNU 버전에서는 입력을 간단하게 grep ''또는awk 1 정식화하여 아직없는 경우 최종 개행을 추가합니다. 그들은 프로세스에서 파일을 복사합니다.이 경우 큰 시간이 걸리지 만 (소스는 너무 커서 읽을 수 없어야합니까?)

 mv file old; grep '' <old >file; touch -r old file

(파일을 수정했기 때문에 체크인하는 파일에서 괜찮을 수도 있지만) 더 조심하지 않으면 하드 링크, 기본이 아닌 권한 및 ACL 등이 손실됩니다.


또는 grep '' file 1<> file그래도 파일을 완전히 읽고 쓸 수 있습니다.
Stéphane Chazelas

-1

이것은 AIX ksh에서 작동합니다.

lastchar=`tail -c 1 *filename*`
if [ `echo "$lastchar" | wc -c` -gt "1" ]
then
    echo "/n" >> *filename*
fi

필자의 경우 파일에 줄 바꿈이 없으면 wc명령은 값을 반환 2하고 줄 바꿈을 씁니다.


피드백은 업 보트 또는 다운 보트 형태로 제공되거나 답변 본문에 질문하지 않아도 답변 / 질문을 더 많이 설명하기 위해 주석으로 요청됩니다. 스택 교환에 오신 것을 환영합니다!
k0pernikus

-1

Patrick Oscity의 답변에 추가하여 특정 디렉토리에 적용하려면 다음을 사용할 수도 있습니다.

find -type f | while read f; do tail -n1 $f | read -r _ || echo >> $f; done

줄 바꿈을 추가하려는 디렉토리 내에서 이것을 실행하십시오.


-1

echo $'' >> <FILE_NAME> 파일 끝에 빈 줄을 추가합니다.

echo $'\n\n' >> <FILE_NAME> 파일 끝에 3 개의 빈 줄이 추가됩니다.


StackExchange, 나는 :-) 당신을 위해 그것을 재미있는 서식을 고정했다
peterh

-1

파일이 Windows 줄 끝으로 끝나고 \r\nLinux에있는 경우이 sed명령을 사용할 수 있습니다 . \r\n마지막 줄이 없으면 추가 합니다.

sed -i -e '$s/\([^\r]\)$/\1\r\n/'

설명:

-i    replace in place
-e    script to run
$     matches last line of a file
s     substitute
\([^\r]\)$    search the last character in the line which is not a \r
\1\r\n    replace it with itself and add \r\n

마지막 줄에 이미가 포함되어 있으면 \r\n검색 정규 표현식이 일치하지 않으므로 아무 일도 일어나지 않습니다.


-1

다음 fix-non-delimited-line과 같은 스크립트를 작성할 수 있습니다 .

#! /bin/zsh -
zmodload zsh/system || exit
ret=0
for file do
  if sysopen -rwu0 -- "$file"; then
    if sysseek -w end -1; then
      read -r x || print -u0
    else
      syserror -p "Can't seek in $file before the last byte: "
      ret=1
    fi
  else
    ret=1
  fi
done
exit $ret

여기에 제공된 솔루션 중 일부와 달리

  • 프로세스를 포크하지 않고 각 파일에 대해 1 바이트 만 읽고 파일을 다시 쓰지 않는다는 점에서 효율적이어야합니다 (개행 만 추가).
  • 심볼릭 링크 / 하드 링크를 끊거나 메타 데이터에 영향을 미치지 않습니다 (또한 ctime / mtime은 줄 바꿈이 추가 될 때만 업데이트 됨)
  • 마지막 바이트가 NUL이거나 멀티 바이트 문자의 일부인 경우에도 정상적으로 작동합니다.
  • 파일 이름에 포함될 수있는 문자 또는 문자가 아닌 문자에 관계없이 정상적으로 작동합니다.
  • 읽을 수 없거나 쓸 수 없거나 찾을 수없는 파일을 올바르게 처리해야하며 그에 따라 오류를보고해야합니다.
  • 빈 파일에 줄 바꿈을 추가해서는 안됩니다 (그러나이 경우 유효하지 않은 탐색에 대한 오류를보고합니다)

예를 들어 다음과 같이 사용할 수 있습니다.

that-script *.txt

또는:

git ls-files -z | xargs -0 that-script

POSIX로, 당신은 기능적으로 동등한 것을 할 수 있습니다.

export LC_ALL=C
ret=0
for file do
  [ -s "$file" ] || continue
  {
    c=$(tail -c 1 | od -An -vtc)
    case $c in
      (*'\n'*) ;;
      (*[![:space:]]*) printf '\n' >&0 || ret=$?;;
      (*) ret=1;; # tail likely failed
    esac
  } 0<> "$file" || ret=$? # record failure to open
done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.