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