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 $?
0
man 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 >> $f
echo ""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-script
POSIXly คุณสามารถทำสิ่งที่เทียบเท่ากับ
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