Dosyanın sonuna nasıl yeni bir satır eklenir?


190

Versiyon kontrol sistemlerini kullanarak, fark söylediğinde gürültüden rahatsız oluyorum No newline at end of file.

Ben de merak ediyordum: Bu mesajlardan kurtulmak için bir dosyanın sonuna nasıl yeni bir satır eklenir?



1
Tüm dosyaları yinelemeli olarak temizleyen aşağıda güzel bir çözüm. Cevap. Üye @Patrick Oscity
Qwerty


İlerlemek için, metin düzenleyicileri sık sık siz ve ortak çalışanlarınızın temiz tutmak için kullanabilecekleri yeni bir satır olmasını sağlama seçeneklerine sahiptir.
Nick,

Yanıtlar:


44

Bir projeyi tekrar tekrar sterilize etmek için bu oneliner'ı kullanıyorum:

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

Açıklama:

  • git ls-files -zHavuzdaki dosyaları listeler. İşlemi belirli dosyalar / dizinlerle sınırlamak istiyorsanız, bazı durumlarda yararlı olabilecek ek bir parametre olarak isteğe bağlı bir model alır. Alternatif olarak, find -print0 ...etkilenen dosyaları listelemek için veya benzer programlar kullanabilirsiniz - yalnızca NULsınırlı girdiler verdiğinden emin olun .

  • while IFS= read -rd '' f; do ... done beyaz boşluk ve / veya yeni satırlar içeren dosya adlarını güvenle işleyerek girişleri yineler.

  • tail -c1 < "$f" bir dosyadan son karakteri okur.

  • read -r _ Sonunda yeni bir satır eksikse, sıfır olmayan bir durumla çıkar.

  • || echo >> "$f" önceki komutun çıkış durumu sıfır değilse, dosyaya yeni bir satır ekler.


Yalnızca dosyalarınızın bir alt kümesini dezenfekte etmek istiyorsanız, bunu da yapabilirsiniz:find -name \*.java | while read f; do tail -n1 $f | read -r _ || echo >> $f; done
Per Lundberg

@ StéphaneChazelas iyi öneriler, bu cevabı benimsemeye çalışacağım.
Patrick Oscity

@PerLundberg ayrıca git ls-filessürüm kontrolünde izlenmeyen dosyaları düzenlemekten sizi kurtaracak bir kalıp da geçirebilirsiniz .
Patrick Oscity

IFS= Ayırıcıyı serbest bırakmak için eklenen @ StéphaneChazelas , çevresindeki boşluğu korumak için iyidir. Boş sonlandırılmış girişler yalnızca adlarında yeni bir satır bulunan, çok uzak alınmış gibi görünen, ancak genel durumu ele almanın daha doğru bir yolu olan dosyalarınız veya dizinleriniz varsa alakalı olur. Küçük bir uyarı olarak: POSIX sh'de bu -dseçenek readmevcut değil.
Patrick Oscity

Evet, bu yüzden benim zsh / bash'ım . Ayrıca tail -n1 < "$f", dosya adlarıyla ilgili sorunlardan kaçınmak için kullanımımı da inceleyin -( tail -n1 -- "$f"çağrılan dosya için çalışmaz -). Cevabın şimdi zsh / bash'a özgü olduğunu açıklığa kavuşturmak isteyebilirsiniz.
Stéphane Chazelas

202

Buyrun :

sed -i -e '$a\' file

Ve alternatif olarak OS X için sed:

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

Bu \n, dosyanın sonuna sadece yeni bir satırla bitmediyse eklenir . Dolayısıyla, iki kez çalıştırırsanız, başka bir yeni satır eklemeyecektir:

$ 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: Kimden man sed: $ Match the last line.Ama belki de sadece kazayla çalışır. Çözümünüz de işe yarıyor.
lbb0

1
Çözümünüz de daha zarif, ve test ettim ve taahhüt ettim, ancak nasıl çalışabilir? Eğer $son satırı ile eşleşir, neden bir dizeye başka yeni satır eklemez zaten bir satır başı karakteri içeren?
l0b0

27
İki farklı anlamı vardır $. Bir regex'in içinde olduğu gibi /<regex>/, "olağan eşleşmenin sonu" anlamına gelir. Aksi halde bir adres olarak kullanılan sed, özel "dosyadaki son satır" anlamını verir. Kod çalışır çünkü varsayılan olarak sed, zaten orada değilse, çıktısına yeni bir satır ekler. "$ A \" kodu sadece "dosyanın son satırıyla eşleşiyor ve hiçbir şey eklemiyor" diyor. Ancak, dolaylı olarak, sed $, henüz orada değilse, işlediği her satıra (bu satır gibi ) yeni satırı ekler .
jwd

1
Manpage ile ilgili: Bahsettiğiniz fiyat teklifi “Adresler” bölümündedir. İçine koymak /regex/, farklı bir anlam verir. FreeBSD broşürleri
jwd

2
Dosya zaten yeni bir satırda bitiyorsa, bu dosyayı değiştirmez, ancak dosyayı yeniden yazar ve zaman damgasını günceller. Bu olabilir veya olmayabilir.
Keith Thompson

39

Bir göz atın:

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

bu yüzden echo "" >> noeol-filehile yapmak gerekir. (Ya da bu dosyaları tanımlamak ve düzeltmek için sormak mı istediniz ?)

edit kaldırıldı ""from echo "" >> foo(@ yuyichao'nın yorumuna bakın) edit2"" yine ekledi ( ama @Keith Thompson'ın yorumuna bakın)


4
""(en azından Bash için) gerekli değildir ve tail -1 | wc -lsonunda, yeni bir hat olmadan dosyayı bulmak için kullanılabilir
yuyichao

5
@yuyichao: Bu ""bash için gerekli değil, ancak echoargümanlar olmadan çağrıldığında hiçbir şey yazamayan uygulamalar gördüm (şu anda bulabileceğim hiçbiri olmasa da). echo "" >> noeol-filemuhtemelen biraz daha sağlamdır. printf "\n" >> noeol-filedaha da öyle.
Keith Thompson

2
@KeithThompson, csh' echoherhangi bir argüman geçmediğinde hiçbir şey çıkmadığı bilinen kişidir. Ama biz olmayan Bourne benzeri kabukları desteklemek için gidiyoruz sonra eğer, bunu yapmalıdır echo ''yerine echo ""olarak echo ""çıktıya ediyorum ""<newline>ile rcveya esmesela.
Stéphane Chazelas

1
@ StéphaneChazelas: Ve tcsh, aksine csh, herhangi bir argüman olmadan çağrıldığında - ayarından bağımsız olarak yeni bir satır yazdırır $echo_style.
Keith Thompson

16

Başka bir çözüm kullanarak ed. Bu çözüm yalnızca son satırı etkiler ve yalnızca \neksikse:

ed -s file <<< w

Esasen dosyayı bir komut dosyası aracılığıyla düzenlemek için açılmakla çalışır, komut dosyası wdosyayı diske geri yazan tek komuttur. ed(1)Man sayfasında bulunan bu cümleyi temel alır :

SINIRLAMA
       (...)

       Metin (ikili olmayan) bir dosya yeni satır karakteriyle sonlandırılmazsa,
       sonra ed okuma / yazma üzerine bir tane ekler. İkili bir durumda
       ed, okuma / yazma üzerine yeni bir satır eklemiyor.

1
Bu benim için yeni bir satır eklemez.
Olhovsky

4
Benim için çalışıyor; Hatta "Newline appended" (Yeni Eklenen) basar (Arch Linux'ta ed-1.10-1).
Stefan Majewsky

12

Bir metin dosyasına eksik, son bir yeni satır eklemek için basit, taşınabilir, POSIX uyumlu bir yol:

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

Bu yaklaşımın tüm dosyayı okumasına gerek yoktur; sadece EOF'ye başvurabilir ve oradan çalışabilir.

Bu yaklaşım aynı zamanda arkanızdan temp dosyaları oluşturmanıza da gerek duymaz (örn. Sed -i), bu nedenle hardlinks etkilenmez.

echo, yalnızca komut değiştirme sonucu boş olmayan bir dize olduğunda dosyaya yeni bir satır ekler. Bunun yalnızca dosya boş değilse ve son bayt yeni satır olmadığında olabileceğini unutmayın.

Dosyanın son baytı yeni bir satırsa, kuyruk onu döndürür, sonra komut değiştirme onu soyar; sonuç boş bir dizedir. -N testi başarısız olur ve yankı çalışmaz.

Dosya boşsa, komut değiştirme işleminin sonucu da boş bir dizedir ve yeniden yankı çalışmaz. Bu arzu edilir, çünkü boş bir dosya geçersiz bir metin dosyası değildir ve boş bir satır içeren boş olmayan bir metin dosyasına eşdeğer değildir.


1
O çalışmaz unutmayın yashdosyasındaki son karakteri (örneğin UTF-8 yerellerde) bir multi-byte karakter veya yerel C ve eğer dosyasındaki son bayt 8 bit kümesi varsa. Diğer kabuklarda (zsh hariç), dosya NUL baytında sona ererse yeni bir satır eklemeyecekti (ancak daha sonra, giriş yeni satır eklendikten sonra bile metin dışı olacağı anlamına gelir).
Stéphane Chazelas

1
@ StéphaneChazelas yash için bir çözüm eklendi .
sorontar

1
Bunu bir klasör ve alt klasördeki her dosya için çalıştırmak mümkün müdür?
Qwerty

12

Ne olursa olsun yeni satır ekleyin:

echo >> filename

Python kullanarak bir tane eklemeden önce yeni bir satır olup olmadığını kontrol etmenin bir yolu:

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

1
Yavaş python başlangıç ​​zamanı nedeniyle python sürümünü herhangi bir döngüde kullanmazdım. Tabii ki istersen python içinde döngü yapabilirdi.
Kevin Cox

2
Python için başlangıç ​​zamanı burada 0,03 saniyedir. Bunun gerçekten problemli olduğunu düşünüyor musunuz?
Alexander

3
Başlangıç zamanı, bir döngü içinde python ararsanız ben döngü yapıyor düşünün demesinin nedeni, yani fark etmez içinde piton. O zaman başlangıç ​​maliyetine yalnızca bir kez katılırsınız. Benim için, başlangıçtaki paranın yarısı kadar bir zaman diliminin yarısından fazlası olduğu için, bunun önemli bir ek yük olduğunu düşünürdüm. (Yine, eğer az sayıda dosya yapıyorsanız, ilgisizdir)
Kevin Cox

2
echo ""daha sağlam görünüyor echo -n '\n'. Ya da kullanabilirsinizprintf '\n'
Keith Thompson

2
Bu benim için iyi çalıştı
Daniel Gomez Rico

8

En hızlı çözüm:

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

  1. Gerçekten hızlı.
    Orta büyüklükteki bir dosyada seq 99999999 >filebu milisaniye sürer.
    Diğer çözümler uzun zaman alıyor:

    [ -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. Kül, bash, lksh, mksh, ksh93, attsh ve zsh'de çalışır ancak yash değildir.

  3. Yeni satır eklemeye gerek yoksa dosya zaman damgasını değiştirmez.
    Burada sunulan diğer tüm çözümler dosyanın zaman damgasını değiştirir.
  4. Yukarıdaki tüm çözümler geçerli POSIX'tir.

Yam için taşınabilir bir çözüme ihtiyacınız varsa (ve yukarıda listelenen tüm diğer mermiler), biraz daha karmaşık olabilir

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

7

Bir dosyanın son baytının yeni bir satır olup olmadığını test etmenin en hızlı yolu, sadece bu son baytı okumaktır. Bu yapılabilir tail -c1 file. Bununla birlikte, bayt değerinin yeni bir satır olup olmadığını sınamanın basit yolu, bir komut genişletme içindeki izleyen yeni satırın genel olarak kaldırılmasına bağlı olarak (örneğin) dosyadaki son karakter bir UTF olduğunda yash'ta başarısız olur. 8 değer.

Doğru, POSIX uyumlu, tümü (makul), dosyanın son baytının yeni bir satır olup olmadığını bulmak için xxd veya hexdump kullanmak mıdır?

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

Ardından, yukarıdaki çıktının karşılaştırılması 0Asağlam bir test sağlayacaktır.
Boş bir dosyaya yeni bir satır eklemekten kaçınmak faydalıdır. Tabii ki,
son karakterini sağlamada başarısız olan dosya 0A:

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

Kısa ve güzel. Bu sadece son baytı okuduğu için çok az zaman alır (EOF'u aramak). Dosyanın büyük olup olmaması önemli değil. Sonra gerekirse yalnızca bir bayt ekleyin.

Geçici dosyaya gerek yoktur, kullanılmaz. Hiçbir sabit bağlantı etkilenmez.

Bu testin iki kez çalıştırılırsa, bu olacak değil başka yeni satır ekleyin.


1
@crw Yararlı bilgiler eklediğine inanıyorum.
sorontar

2
Ne POSIX yardımcı programlarının xxdne hexdumpolduğuna dikkat edin. POSIX araç testinde od -An -tx1bir baytın onaltılık değerini elde etmek gerekir.
Stéphane Chazelas

@ StéphaneChazelas Lütfen cevap olarak yazınız; Buraya çok fazla kez bakmaya geldim :)
kelvin

@kelvin, ben güncelledik cevabımı
Stéphane Chazelas

POSIX’in LF değerini 0x0a olmasını garanti etmediğini unutmayın. Bugünlerde oldukça nadir olmasına rağmen (EBCDIC tabanlı olanların) olmadığı POSIX sistemleri hala var.
Stéphane Chazelas

4

Dosyayı en son düzenleyen kullanıcının düzenleyicisini düzeltirseniz daha iyi olursunuz. Dosyayı düzenleyen son kişiyseniz, hangi editörü kullanıyorsunuz, metin arkadaşı tahmin ediyorum ..?


2
Vim söz konusu editördür. Ama genel olarak haklısın, sadece
semptomları

6
vim için, size yolumdan gitmek ve ikili dosyasını on kurtarmak için vim almak için dans yapmak zorunda değil sadece bu dansı yapmayın - dosyanın sonuna yeni bir satır ekleyin. VEYA, varolan dosyaları basitçe düzeltmek için onları vim'de açın ve dosyayı kaydedin; vim sizin için eksik olan yeni satırı 'düzeltecektir' (birden fazla dosya için kolayca komut dosyası
yazılabilir

3
Benim emacsdosyanın sonuna bir yeni satır eklemeyin.
enzotib

2
@ AD7six yorumu için teşekkürler, orijinal dosyanın sonunda nasıl yeni bir satır sonu olamayacağı hakkında bir şeyler işlediğimde hayalet raporlar almaya devam ediyorum. Vim ile bir dosyayı nasıl düzenlersem düzelteyim, oraya yeni bir satır koymayı başaramıyorum. Yani sadece bunu yaparken vim.
Steven Lu,

1
@enzotib: Ben (setq require-final-newline 'ask)benim içinde.emacs
Keith Thompson

3

Bazı boru hatlarını işlerken hızlıca yeni bir satır eklemek istiyorsanız, şunu kullanın:

outputting_program | { cat ; echo ; }

Aynı zamanda POSIX uyumludur.

Sonra, elbette, onu bir dosyaya yönlendirebilirsiniz.


2
Bunu bir boru hattında kullanabilmem faydalı olur. Bu, CSV dosyasındaki satır sayısını, başlık hariç saymamı sağlıyor. Ayrıca, yeni bir satır veya satır başı ile bitmeyen Windows dosyalarında doğru bir satır sayımı elde etmenize yardımcı olur. cat file.csv | tr "\r" "\n" | { cat; echo; } | sed "/^[[:space:]]*$/d" | tail -n +2 | wc -l
Kyle Tolle

3

Sunulan girişde boş değer yoktur:

paste - <>infile >&0

... her zaman yalnızca bir dolgunun kuyruğuna yeni bir satır eklemek için yeterli olurdu. Ve doğru dosyayı almak için yalnızca bir defa girdi dosyasını okuması gerekir.


Stdin ve stdout aynı açık dosya açıklamasını paylaştığı gibi çalışmaz (yani dosya içindeki imleç). Onun paste infile 1<> infileyerine ihtiyacın olacak .
Stéphane Chazelas

2

Soruyu doğrudan cevaplamamasına rağmen, işte yeni satırda bitmeyen dosyaları saptamak için yazdığım ilgili bir komut dosyası. Çok hızlı.

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 betiği (isteğe bağlı olarak sıralanmış) dosya adlarının bir listesini stdin'den okur ve her dosya için, dosyanın yeni bir satırda bitip bitmeyeceğini belirlemek için son baytı okur. Çok hızlı çünkü her dosyanın içeriğini okumaktan kaçınıyor. Okuduğu her dosya için bir satır çıktısı alır, "error:" ile bir tür hata oluşursa, "empty:", eğer boş ise (newline ile bitmiyor!), "EOL:" (" satır ") dosya newline ile bitiyorsa ve" no EOL: "ise dosya newline ile bitmiyorsa.

Not: Betik, yeni satırlar içeren dosya adlarını işlemez. Bir GNU veya BSD sistemindeyseniz, olası tüm dosya adlarını, bulmak için -print0, sıralamak için -z ve perl için -0 ekleyerek kullanabilirsiniz:

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 }
'

Elbette, dosya isimlerini çıktıda yeni satırlarla kodlamanın bir yolunu bulmanız gerekiyordu (okuyucu için bir alıştırma olarak bırakıldı).

İstenirse çıktı, biri olmayan dosyalara yeni bir satır eklemek için filtrelenebilir.

 echo >> "$filename"

Son satırsonu eksikliği kodlarda hatalara neden olabilir, çünkü bazı kabuk sürümleri ve diğer yardımcı programlar, böyle bir dosyayı okurken eksik olan son satırları doğru şekilde işlemeyecektir.

Deneyimlerime göre, son bir yeni satırın olmayışı, dosyaları düzenlemek için çeşitli Windows yardımcı programlarının kullanılmasından kaynaklanıyor. Vim'in bir dosyayı düzenlerken eksik bir son satırın neden olduğunu görmedim, ancak bu tür dosyalar hakkında rapor yazacaktır.

Son olarak, aşağıdakiler gibi yeni satırda bitmeyen dosyaları yazdırmak için dosya adı girişleri üzerinde döngü yapabilen daha kısa (ancak daha yavaş) komut dosyaları vardır:

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

1

vi/ vim/ exEditörler otomatik eklemek <EOL>dosya zaten olmadıkça EOF.

O zaman ikisini de deneyin:

vi -ecwq foo.txt

hangi eşdeğerdir:

ex -cwq foo.txt

Test yapmak:

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

Birden fazla dosyayı düzeltmek için , şunları kontrol edin: Birçok dosya için 'Dosyanın sonunda yeni satır yok' düzeltmesi nasıl yapılır? SO'da

Bu neden bu kadar önemli? Dosyalarımızı POSIX uyumlu tutmak için .


0

Kabul edilen yanıtı geçerli dizindeki tüm dosyalara uygulamak için (artı alt dizinler):

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

Bu Linux (Ubuntu) üzerinde çalışır. OS X'te muhtemelen kullanmanız gerekir -i ''(denenmemiş).


4
İçindeki find .dosyalar dahil tüm dosyaları listelediğine dikkat edin .git. Hariç tutulacak:find . -type f -not -path './.git/*' -exec sed -i -e '$a\' {} \;
friederbluemle

Keşke çalıştırmadan önce bu yorumu / düşünceyi okumuş olsaydım. Oh iyi.
kstev

0

En azından GNU versiyonlarında, eğer mevcut değilse son bir yeni satır ekleyerek girişini basitçe grep ''ya daawk 1 kuralsızlaştırır. Dosyayı işlem sırasında kopyalarlar; bu işlem büyük olduğunda zaman alır (ancak kaynak yine de okumak için çok büyük olmamalıdır?) Ve siz istediğiniz bir şey yapmadıkça modtime’yı günceller

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

(Her ne kadar değiştirmiş olduğunuz için kontrol ettiğiniz bir dosyada tamam da olsa da) ve daha da dikkatli olmadığınız sürece hardlinks, varsayılan olmayan izinleri ve ACL'leri vb. kaybeder.


Ya da sadece grep '' file 1<> file, bu yine de dosyayı okuyup yazacaktır.
Stéphane Chazelas

-1

Bu AIX ksh’de çalışır:

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

Benim durumumda eğer dosyada yeni satır eksikse, wckomut bir değer döndürür 2ve yeni satır yazarız.


Geribildirim, yukarı veya aşağı oy şeklinde gelecek veya cevaplarınızı / sorularınızı daha fazla özetlemeniz için yorumlarda sizden cevap istenecek, cevap için soru sormayacaksınız. Bu noktaya devam et, stackexchange'e hoş geldiniz!
k0pernikus

-1

Patrick Oscity'nin cevabını eklemek , sadece belirli bir dizine uygulamak istiyorsanız, şunları da kullanabilirsiniz:

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

Bunu, yeni satır eklemek istediğiniz dizininizde çalıştırın.


-1

echo $'' >> <FILE_NAME> Dosyanın sonuna boş bir satır ekler.

echo $'\n\n' >> <FILE_NAME> Dosyanın sonuna 3 boş satır ekleyecektir.



-1

Dosyanız Windows satır sonları ile sonlandırılıyorsa \r\nve Linux'taysanız bu sedkomutu kullanabilirsiniz . Henüz \r\norada değilse, yalnızca son satıra eklenir :

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

Açıklama:

-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

Son satır zaten bir içeriyorsa \r\n, arama regexp eşleşmeyecek, bu nedenle hiçbir şey olmayacak.


-1

Gibi bir fix-non-delimited-linekomut dosyası yazabilirsiniz :

#! /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

Burada verilen çözümlerin bazılarının aksine,

  • herhangi bir işlemi gerçekleştirmemesi, her dosya için yalnızca bir bayt okması ve dosyayı yeniden yazmaması için verimli olmalıdır (yalnızca yeni bir satır ekler)
  • sembolik linkleri / sabit linkleri kırmaz veya meta verileri etkilemez (ayrıca, ctime / mtime yalnızca bir yeni satır eklendiğinde güncellenir)
  • Son bayt bir NUL olsa veya bir çok baytlık karakterin parçası olsa bile Tamam çalışması gerekir.
  • dosya adlarının hangi karakterleri veya karakterleri içermemesine bakmaksızın Tamam çalışması gerekir.
  • Düzgünce okunamayan veya okunamayan veya görülmeyen dosyaları işlemelidir (ve hataları buna göre raporlayın)
  • Boş dosyalara yeni bir satır eklememelidir (ancak bu durumda geçersiz bir arama ile ilgili bir hata bildirir)

Mesela şu şekilde kullanabilirsiniz:

that-script *.txt

veya:

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

POSIXly ile, işlevsel olarak eşdeğer bir şeyi yapabilirsiniz

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.