No newline at end of fileโดยใช้ระบบการควบคุมรุ่นที่ฉันได้รับรำคาญที่เสียงเมื่อต่างกล่าวว่า
ดังนั้นฉันสงสัยว่า: วิธีเพิ่มบรรทัดใหม่ที่ท้ายไฟล์เพื่อกำจัดข้อความเหล่านั้นได้อย่างไร
No newline at end of fileโดยใช้ระบบการควบคุมรุ่นที่ฉันได้รับรำคาญที่เสียงเมื่อต่างกล่าวว่า
ดังนั้นฉันสงสัยว่า: วิธีเพิ่มบรรทัดใหม่ที่ท้ายไฟล์เพื่อกำจัดข้อความเหล่านั้นได้อย่างไร
คำตอบ:
ในการฆ่าเชื้อซ้ำโครงการฉันใช้ 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รายการ -delimited
while IFS= read -rd '' f; do ... done วนซ้ำผ่านรายการจัดการชื่อไฟล์ที่มีช่องว่างและ / หรือบรรทัดใหม่ได้อย่างปลอดภัย
tail -c1 < "$f" อ่านอักขระตัวสุดท้ายจากไฟล์
read -r _ ออกด้วยสถานะการออกที่ไม่ใช่ศูนย์หากบรรทัดใหม่ต่อท้ายหายไป
|| echo >> "$f" ผนวกบรรทัดใหม่เข้ากับไฟล์หากสถานะการออกของคำสั่งก่อนหน้านี้ไม่ใช่ศูนย์
find -name \*.java | while read f; do tail -n1 $f | read -r _ || echo >> $f; done
                    git ls-filesที่จะช่วยให้คุณประหยัดจากการแก้ไขไฟล์ที่ไม่ได้ถูกติดตามในการควบคุมเวอร์ชัน
                    IFS= เพื่อยกเลิกการตั้งค่าตัวคั่นเป็นสิ่งที่ดีเพื่อรักษาช่องว่างโดยรอบ รายการที่ถูกยกเลิกเป็นโมฆะมีความเกี่ยวข้องเฉพาะเมื่อคุณมีไฟล์หรือไดเรกทอรีที่มีบรรทัดใหม่ในชื่อของพวกเขาซึ่งดูเหมือนจะดึงข้อมูลได้ไกล แต่เป็นวิธีที่ถูกต้องมากขึ้นในการจัดการกรณีทั่วไปฉันเห็นด้วย เช่นเดียวกับข้อแม้เล็ก ๆ : -dตัวเลือกที่readจะไม่สามารถใช้ได้ใน POSIX sh
                    tail -n1 < "$f"เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับชื่อไฟล์ที่ขึ้นต้นด้วย-(ใช้tail -n1 -- "$f"ไม่ได้กับไฟล์ที่เรียกว่า-) คุณอาจต้องการชี้แจงว่าคำตอบคือตอนนี้ zsh / bash เฉพาะ
                    ไปเลย :
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 $?
0man sed: $      Match the last line.แต่บางทีมันอาจทำงานได้โดยบังเอิญ โซลูชันของคุณยังใช้งานได้
                    $มีสองความหมายที่แตกต่างกันอยู่ ภายใน regex เช่นกับฟอร์ม/<regex>/มันมีความหมาย "ตรงกับจุดสิ้นสุดของบรรทัด" ตามปกติ มิฉะนั้นใช้เป็นที่อยู่ sed ให้ความหมายพิเศษ "บรรทัดสุดท้ายในไฟล์" รหัสใช้งานได้เพราะ sed โดยค่าเริ่มต้นจะขึ้นบรรทัดใหม่ต่อท้ายเอาต์พุตหากยังไม่มีอยู่ รหัส "$ a \" เพิ่งพูดว่า "ตรงกับบรรทัดสุดท้ายของไฟล์และไม่ต้องเพิ่มอะไรเลย" แต่โดยนัยแล้ว sed เพิ่มบรรทัดใหม่ให้กับทุกบรรทัดที่ประมวลผล (เช่น$บรรทัดนี้) หากยังไม่มีอยู่
                    /regex/นั้นให้ความหมายที่ต่างออกไป manpages ของ FreeBSD นั้นให้ความรู้น้อยกว่านี้ฉันคิดว่า: freebsd.org/cgi/man.cgi?query=sed
                    ไปดูกัน:
$ echo -n foo > foo 
$ cat foo
foo$
$ echo "" >> foo
$ cat foo
fooดังนั้นecho "" >> noeol-fileควรทำเคล็ดลับ (หรือคุณหมายถึงขอให้ระบุไฟล์เหล่านี้และแก้ไขไฟล์เหล่านั้น?)
แก้ไขลบออก""จากจากecho "" >> foo(ดูความคิดเห็นของ @ yuyichao) edit2เพิ่ม""อีกครั้ง ( แต่ดูความคิดเห็นของ @Keith
 Thompson)
""ไม่จำเป็น (อย่างน้อยสำหรับทุบตี) และtail -1 | wc -lสามารถนำมาใช้เพื่อหาไฟล์ได้โดยไม่ต้องขึ้นบรรทัดใหม่ในตอนท้าย
                    ""ไม่จำเป็นสำหรับทุบตี แต่ฉันได้เห็นechoการใช้งานที่พิมพ์อะไรเมื่อเรียกโดยไม่มีข้อโต้แย้ง (แม้ว่าไม่มีสิ่งที่ฉันสามารถหาได้ทำตอนนี้)  echo "" >> noeol-fileอาจจะแข็งแกร่งกว่าเล็กน้อย  printf "\n" >> noeol-fileยิ่งไปกว่านั้น
                    csh's echoเป็นหนึ่งที่รู้จักกันไปไม่มีอะไรส่งออกเมื่อไม่ได้ผ่านการโต้แย้งใด ๆ แต่ถ้าเราจะให้การสนับสนุนเปลือกหอยที่ไม่ใช่บอร์นเราควรทำให้มันecho ''เป็นแทนที่จะecho ""เป็นecho ""ouput ""<newline>กับrcหรือesเป็นตัวอย่าง
                    tcshไม่เหมือนcsh, พิมพ์ขึ้นบรรทัดใหม่เมื่อเรียกด้วยไม่มีข้อโต้แย้ง - $echo_styleไม่คำนึงถึงการตั้งค่าของ
                    edทางออกก็ใช้ วิธีนี้มีผลกับบรรทัดสุดท้ายเท่านั้นและ\nจะหายไป:
ed -s file <<< wมันเป็นงานเปิดไฟล์สำหรับการแก้ไขผ่านสคริปต์สคริปต์เป็นwคำสั่งเดียวที่เขียนไฟล์กลับไปที่ดิสก์ มันขึ้นอยู่กับประโยคนี้พบในed(1)หน้าคน:
ข้อ จำกัด
       ( ... )
       หากไฟล์ข้อความ (ไม่ใช่ไบนารี) ไม่ได้ถูกยกเลิกด้วยอักขระขึ้นบรรทัดใหม่
       จากนั้น ed จะผนวกหนึ่งในการอ่าน / เขียนมัน ในกรณีของเลขฐานสอง
       ไฟล์ ed ไม่ต่อท้ายบรรทัดใหม่ในการอ่าน / เขียน
              วิธีที่ง่ายและพกพาได้และเป็นไปตามมาตรฐาน POSIX เพื่อเพิ่มบรรทัดใหม่ที่ขาดหายไปซึ่งเป็นไฟล์ข้อความ:
[ -n "$(tail -c1 file)" ] && echo >> fileวิธีนี้ไม่จำเป็นต้องอ่านไฟล์ทั้งหมด มันสามารถหา EOF และทำงานได้จากที่นั่น
วิธีการนี้ไม่จำเป็นต้องสร้างไฟล์ชั่วคราวที่ด้านหลังของคุณ (เช่น sed -i) ดังนั้นลิงก์จะไม่ได้รับผลกระทบ
echo ต่อท้ายบรรทัดใหม่ให้กับไฟล์ก็ต่อเมื่อผลลัพธ์ของการทดแทนคำสั่งเป็นสตริงที่ไม่ว่างเปล่า โปรดทราบว่าสิ่งนี้สามารถเกิดขึ้นได้หากไฟล์ไม่ว่างเปล่าและไบต์สุดท้ายไม่ใช่บรรทัดใหม่
หากไบต์สุดท้ายของไฟล์เป็นบรรทัดใหม่ tail จะส่งคืนจากนั้นการแทนที่คำสั่งจะลบทิ้ง ผลลัพธ์คือสตริงว่าง การทดสอบ -n ล้มเหลวและเสียงก้องไม่ทำงาน
หากไฟล์นั้นว่างเปล่าผลลัพธ์ของการทดแทนคำสั่งจะเป็นสตริงว่างและ echo จะไม่ทำงานอีกครั้ง สิ่งนี้เป็นที่ต้องการเนื่องจากไฟล์เปล่าไม่ใช่ไฟล์ข้อความที่ไม่ถูกต้องและไม่เท่ากับไฟล์ข้อความที่ไม่ว่างเปล่าที่มีบรรทัดว่าง
yashหากอักขระตัวสุดท้ายในไฟล์เป็นอักขระแบบหลายไบต์ (ในโลแคล UTF-8 เป็นต้น) หรือหากโลแคลเป็น C และไบต์สุดท้ายในไฟล์มีชุดบิตที่ 8 ด้วยเชลล์อื่น (ยกเว้น zsh), มันจะไม่เพิ่มบรรทัดใหม่หากไฟล์สิ้นสุดในไบต์ NUL (แต่หลังจากนั้นอีกครั้ง, นั่นหมายความว่าอินพุตจะไม่ใช่ข้อความแม้ว่าจะเพิ่มบรรทัดใหม่)
                    เพิ่มบรรทัดใหม่โดยไม่คำนึงถึง:
echo >> filenameนี่คือวิธีตรวจสอบว่ามีการขึ้นบรรทัดใหม่ที่จุดสิ้นสุดก่อนที่จะเพิ่มอีกอันหรือไม่โดยใช้ Python:
f=filename; python -c "import sys; sys.exit(open(\"$f\").read().endswith('\n'))" && echo >> $fecho ""echo -n '\n'ดูเหมือนว่ามีประสิทธิภาพมากขึ้นกว่า หรือคุณสามารถใช้printf '\n'
                    ทางออกที่เร็วที่สุดคือ:
[ -n "$(tail -c1 file)" ] && printf '\n' >>file มันเร็วจริงๆ 
ในไฟล์ขนาดกลาง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ใช้งานได้กับเถ้า, ทุบตี, lksh, mksh, ksh93, attsh และ zsh แต่ไม่ได้ล้าง
หากคุณต้องการโซลูชันแบบพกพาเพื่อ yash (และเชลล์อื่น ๆ ทั้งหมดที่ระบุไว้ข้างต้น) มันอาจจะซับซ้อนกว่านี้เล็กน้อย:
f=file
if       [ "$(tail -c1 "$f"; echo x)" != "$(printf '\nx')" ]
then     printf '\n' >>"$f"
fiวิธีที่เร็วที่สุดในการทดสอบว่าไบต์สุดท้ายของไฟล์คือการขึ้นบรรทัดใหม่คือการอ่านไบต์สุดท้ายเท่านั้น tail -c1 fileที่สามารถทำได้ด้วย อย่างไรก็ตามวิธีง่าย ๆ ในการทดสอบว่าค่าไบต์เป็นบรรทัดใหม่หรือไม่ขึ้นอยู่กับการลบเชลล์ตามปกติของการขึ้นบรรทัดใหม่ภายในการขยายคำสั่งล้มเหลว (ตัวอย่าง) ใน yash เมื่ออักขระตัวสุดท้ายในไฟล์เป็น UTF- 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) ไม่สำคัญว่าไฟล์ใหญ่หรือไม่ จากนั้นเพิ่มเพียงหนึ่งไบต์หากจำเป็น
ไม่มีไฟล์ temp ที่จำเป็นและไม่ได้ใช้ ไม่มีผลกระทบต่อการเชื่อมโยง
หากการทดสอบนี้ทำงานสองครั้งจะไม่เพิ่มบรรทัดใหม่
xxdมิได้hexdumpเป็นสาธารณูปโภค POSIX ใน POSIX toolchest od -An -tx1จะต้องมีค่า hex ของไบต์
                    คุณดีกว่าการแก้ไขตัวแก้ไขของผู้ใช้ที่แก้ไขไฟล์ครั้งล่าสุด หากคุณเป็นคนสุดท้ายที่จะแก้ไขไฟล์ - คุณใช้โปรแกรมแก้ไขอะไรฉันเดาข้อความ?
emacsจะไม่เพิ่มบรรทัดใหม่เมื่อสิ้นสุดไฟล์
                    (setq require-final-newline 'ask)ในของฉัน.emacs
                    หากคุณต้องการเพิ่มบรรทัดใหม่อย่างรวดเร็วเมื่อประมวลผลไปป์ไลน์ให้ใช้:
outputting_program | { cat ; echo ; }มันยังสอดคล้องกับ POSIX
แน่นอนว่าคุณสามารถเปลี่ยนเส้นทางไปยังไฟล์ได้
cat file.csv | tr "\r" "\n" | { cat; echo; } | sed "/^[[:space:]]*$/d" | tail -n +2 | wc -l
                    ระบุว่าไม่มีค่า null ในอินพุต:
paste - <>infile >&0... จะพอเพียงต่อท้ายบรรทัดใหม่ต่อท้ายท้ายของ infile ถ้ามันไม่มีอยู่แล้ว และมันต้องการเพียงอ่านไฟล์อินพุตผ่านครั้งเดียวเพื่อทำให้ถูกต้อง
paste infile 1<> infileแทน
                    แม้ว่ามันจะไม่ตอบคำถามโดยตรง แต่นี่เป็นสคริปต์ที่เกี่ยวข้องที่ฉันเขียนเพื่อตรวจหาไฟล์ที่ไม่ได้ขึ้นบรรทัดใหม่ มันเร็วมาก
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 และสำหรับทุกไฟล์ที่อ่านเป็นไบต์สุดท้ายเพื่อพิจารณาว่าไฟล์สิ้นสุดในบรรทัดใหม่หรือไม่ มันเร็วมากเพราะหลีกเลี่ยงการอ่านเนื้อหาทั้งหมดของแต่ละไฟล์ มันส่งออกหนึ่งบรรทัดสำหรับแต่ละไฟล์ที่อ่านนำหน้าด้วย "ข้อผิดพลาด:" หากเกิดข้อผิดพลาดบางประเภท "ว่าง:" ถ้าไฟล์นั้นว่างเปล่า (ไม่ลงท้ายด้วยการขึ้นบรรทัดใหม่!), "EOL:" ("ท้ายสุดของ บรรทัด ") หากไฟล์ลงท้ายด้วย newline และ" no EOL: "หากไฟล์ไม่ลงท้ายด้วย newline
หมายเหตุ: สคริปต์ไม่ได้จัดการชื่อไฟล์ที่มีการขึ้นบรรทัดใหม่ หากคุณอยู่ในระบบ GNU หรือ BSD คุณสามารถจัดการชื่อไฟล์ที่เป็นไปได้ทั้งหมดโดยเพิ่ม -print0 เพื่อค้นหา, -z เพื่อจัดเรียงและ -0 ถึง Perl เช่นนี้:
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 ต่างๆเพื่อแก้ไขไฟล์ ฉันไม่เคยเห็นเป็นกลุ่มเลยทำให้เกิดบรรทัดใหม่สุดท้ายที่หายไปเมื่อแก้ไขไฟล์แม้ว่าจะรายงานไฟล์ดังกล่าว
สุดท้ายมีสคริปต์ที่สั้นกว่า (แต่ช้ากว่า) ซึ่งสามารถวนรอบอินพุตไฟล์ของพวกเขาเพื่อพิมพ์ไฟล์เหล่านั้นซึ่งไม่ได้ลงท้ายด้วยการขึ้นบรรทัดใหม่เช่น:
/usr/bin/perl -ne 'print "$ARGV\n" if /.\z/' -- FILE1 FILE2 ...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 เข้ากันได้
วิธีใช้คำตอบที่ยอมรับกับไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน (รวมถึงไดเรกทอรีย่อย):
$ find . -type f -exec sed -i -e '$a\' {} \;สิ่งนี้ใช้ได้กับ Linux (Ubuntu) บน OS X คุณอาจต้องใช้-i ''(ยังไม่ทดลอง)
find .รายการไฟล์ทั้งหมดรวมถึงไฟล์.gitมา วิธียกเว้น:find . -type f -not -path './.git/*' -exec sed -i -e '$a\' {} \;
                    อย่างน้อยในเวอร์ชัน GNU เพียงgrep ''awk 1ป้อน canonicalizes หรือป้อนให้เพิ่มบรรทัดใหม่สุดท้ายหากยังไม่ปรากฏ พวกเขาจะคัดลอกไฟล์ในกระบวนการซึ่งจะใช้เวลาหากมีขนาดใหญ่ (แต่แหล่งที่มาไม่ควรใหญ่เกินไปที่จะอ่านต่อไปหรือไม่) และอัปเดต modtime เว้นแต่คุณจะทำสิ่งที่ชอบ
 mv file old; grep '' <old >file; touch -r old file(แม้ว่าอาจจะไม่เป็นไรสำหรับไฟล์ที่คุณกำลังเช็คอินเพราะคุณแก้ไขมัน) และมันจะสูญเสียลิงก์, สิทธิ์ที่ไม่ใช่ค่าเริ่มต้นและ ACLs เป็นต้นเว้นแต่ว่าคุณจะระมัดระวังมากกว่านี้
grep '' file 1<> fileว่าจะยังคงอ่านและเขียนไฟล์อย่างเต็มที่
                    สิ่งนี้ใช้ได้ใน AIX ksh:
lastchar=`tail -c 1 *filename*`
if [ `echo "$lastchar" | wc -c` -gt "1" ]
then
    echo "/n" >> *filename*
fiในกรณีของฉันหากไฟล์หายไปขึ้นบรรทัดใหม่wcคำสั่งจะคืนค่าเป็น2และเราเขียนขึ้นบรรทัดใหม่
การเพิ่มคำตอบของ Patrick Oscityหากคุณต้องการนำไปใช้กับไดเรกทอรีเฉพาะคุณสามารถใช้:
find -type f | while read f; do tail -n1 $f | read -r _ || echo >> $f; done
เรียกใช้สิ่งนี้ภายในไดเรกทอรีที่คุณต้องการเพิ่มบรรทัดใหม่
echo $'' >> <FILE_NAME> จะเพิ่มบรรทัดว่างที่ท้ายไฟล์
echo $'\n\n' >> <FILE_NAME> จะเพิ่ม 3 บรรทัดว่างในตอนท้ายของไฟล์
หากไฟล์ของคุณถูกยุติด้วยการสิ้นสุดบรรทัดWindows\r\nและคุณอยู่ใน Linux คุณสามารถใช้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แล้ว regexp การค้นหาจะไม่ตรงกันดังนั้นจึงไม่มีอะไรเกิดขึ้น
คุณสามารถเขียน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ตรงกันข้ามกับโซลูชันบางตัวที่ให้ไว้ที่นี่
คุณสามารถใช้มันเป็นเช่น:
that-script *.txtหรือ:
git ls-files -z | xargs -0 that-scriptPOSIXly คุณสามารถทำสิ่งที่เทียบเท่ากับ
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