Linux'ta grep ile dos satır sonlarını (CRLF) içeren dosyaları nasıl ararsınız?


126

Linux'ta grep ile dos satır sonlarını içeren dosyaları aramak istiyorum. Bunun gibi bir şey:

grep -IUr --color '\r\n' .

Yukarıdakiler rn, istenen şey olmayan gerçekle eşleşiyor gibi görünüyor .

Bunun çıktısı, crlf'yi bu şekilde lf'ye dönüştürmek için xargs aracılığıyla todos'a aktarılacaktır.

grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'

2
Dos2unix'i denediniz mi? Satır sonlarını otomatik olarak düzeltir.
sblundy

Tam olarak emin değilim, ancak "ve" içindeki kalıbı alıntılamak arasında bir fark var. "Kaçış dizileri uygun dize olarak yorumlanır, bu nedenle" \ r "" \\ r "ve" ile eşdeğer olacaktır. \ r "'nin' ile eşdeğeri yoktur (en azından bu gösterimde).
Anticom

Anticom: Bu durumda "ve" arasındaki farkın alakasız olduğu konusunda haklısınız; ancak, genellikle "çevrelenmiş dizeler zayıf alıntılanmış ve" güçlü alıntılar yapıldığından bunlar farklıdır. Avantaj aldığım en büyük şey, $ genişletmelerinin veya `` zayıf alıntılanmış dizelerde genişlememesidir. Daha fazla alıntı yapmak için bash-hacker'ları görün .
bschlueter

4
En kolay yol, switch dos2unixile modern kullanmaktır -ic. LF dosyaları için unix2dos ile arama yapabilirsiniz -ic. Dosyaları değiştirmez. Sadece rapor et.
gavenkoa

3
Bu, Linux'ta Windows satır sonları / satır sonları ile ilgili herhangi bir soru için en iyi cevap olduğundan, bunları terminalde komutla görebileceğinizi belirtmekte fayda var cat -v somefile.txt; olarak ^M
görünürler

Yanıtlar:


122

Grep dizenize değişmez bir Satır Başı karakteri girmek için Ctrl+ V, Ctrl+ kullanın M. Yani:

grep -IUr --color "^M"

işe yarayacak - ^Mönerdiğim gibi girdiğiniz gerçek bir CR varsa.

Dosyaların listesini istiyorsanız, -lseçeneği de eklemek istersiniz .

açıklama

  • -I ikili dosyaları yoksay
  • -Ugrep'in CR karakterlerini çıkarmasını engeller. Varsayılan olarak, bir metin dosyası olduğuna karar verirse bunu yapacaktır.
  • -r her dizinin altındaki tüm dosyaları özyinelemeli olarak okuyun.

3
İşe yarayacak hızlı bir hack olarak, ancak insan okumalı çözümün şöyle olacağını düşünüyorum: grep $ '\ r' / bash shell only / veya grepprintf '\r'
akostadinov

5
@akostadinov +1, Ancak ters işaretler yorumunuzdan yorumlandı;) İkinci seçenek başka bir deyişle olabilir grep $(printf '\r'). Ama bash'ı içeren çoğu pratik kullanım için, sadık kalırım $'\r'.
jankes

3
Not: Bu seçenek -Uyalnızca Windows (veya cygwin) için geçerlidir, ancak burada kritiktir. Windows'ta komut onsuz çalışmayacaktır.
sleske

3
Seçeneğin amacı nedir -I? Kılavuza göre, bana öyle geliyor ki ikili dosyalar eşleşmiyor olarak kabul ediliyor. -IVe -U(ikili türü zorlar) kombinasyonu, tüm dosyaların eşleşmeyen olarak kabul edilmesine neden olmamalı mı ?
Jānis Elmeris

3
Eklenti seçeneği olarak '-l' bayrağından bahsediyorsunuz, ancak bence birincil yanıta dahil edilmesi gerekiyor çünkü soru aslında bir dosya listesi istiyor. Ayrıca, daha hızlı bir aramayla sonuçlanır.
arr_sea

169

grep muhtemelen bunun için istediğiniz araç değil. Her dosyadaki her eşleşen satır için bir satır yazdıracaktır. Diyelim ki 10 satırlık bir dosyada 10 kez todos çalıştırmak istemiyorsanız, grep bunu yapmanın en iyi yolu değildir. Ağaçtaki her dosyada dosyayı çalıştırmak için find'ı kullanmak ve ardından "CRLF" için bunu incelemek, dos stili satır sonlarına sahip her dosya için size bir satır çıktı verecektir:

find . -not -type d -exec file "{}" ";" | grep CRLF

sana şöyle bir şey alacak:

./1/dos1.txt: ASCII text, with CRLF line terminators
./2/dos2.txt: ASCII text, with CRLF line terminators
./dos.txt: ASCII text, with CRLF line terminators

Bunu zaten çözmüştüm ama yine de teşekkürler. grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'
Tim Abell

5
Grep'in -l seçeneği, her dosyadaki eşleşmeleri listelemek yerine yalnızca dosyaları listelemesini (bir kez) söyler.
pjz

8
fileProgramın bu (belgelenmemiş, insan tüketimine yönelik) davranışına güvenmek için iyi bir çözüm değil . Bu çok kırılgan. (Sadece bir) örnek için: XML dosyalarında, satırsonu türünden bağımsız olarak fileraporlarda çalışmaz XML document text.
leonbloy

1
@leonbloy, seçenek -m /dev/nullbenim find (GNU findutils) 4.4.2(Ubuntu 12.04) 'te küçük harfli gibi görünüyor .
EarlCrapstone

8
Bu cevabı en çok beğendim. Ben basitçe yaptımfind . -type f | xargs file | grep CRLF
Brianz

58

11
Teşekkürler! Daha sonra gelenleri netleştirmek için, bash el kitabında "$ 'dizge' biçimindeki kelimeler özel olarak ele alınır. Kelime dizgeye genişler ve ANSI C standardı tarafından belirtildiği gibi ters eğik çizgi kaçış karakterleri değiştirilir." (ayrıca desteklenen kodların listesine bakın )
Sean Gugler

5
Peki bu bash'a özel mi? Varsa not edilmelidir.
cubuspl42

kötü autocrlf ile git için şunu kullanırdım: grep -IUlrZ $ '\ r' | xargs -0 sed -zbi 's / \ r // g'
buzard

17

Grep sürümünüz -P (--perl-regexp) seçeneğini destekliyorsa ,

grep -lUP '\r$'

kullanılabilir.


8
# list files containing dos line endings (CRLF)

cr="$(printf "\r")"    # alternative to ctrl-V ctrl-M

grep -Ilsr "${cr}$" . 

grep -Ilsr $'\r$' .   # yet another & even shorter alternative

3

Sorgu aramaydı ... Benzer bir sorunum var ... birisi sürüm kontrolüne karışık satır sonları gönderdi, bu yüzden artık 0x0d 0x0d 0x0asatır sonları olan bir sürü dosyamız var. Bunu not et

grep -P '\x0d\x0a'

tüm satırları bulur, oysa

grep -P '\x0d\x0d\x0a'

ve

grep -P '\x0d\x0d'

çizgi bulmadığından grep içinde "başka" bir şeyler olabilir, konu satır bitiş kalıplarına gelince ... ne yazık ki benim için!


3

Unix'te dosya komutunu kullanabilirsiniz. Size dosyanın karakter kodlamasını satır sonlandırıcılarla birlikte verir.

$ file myfile
myfile: ISO-8859 text, with CRLF line terminators
$ file myfile | grep -ow CRLF
CRLF  

1

Benim gibi, minimalist unixiniz file komutu gibi incelikler içermiyorsa ve grep ifadelerinizdeki ters eğik çizgiler işbirliği yapmıyorsa, şunu deneyin:

$ for file in `find . -type f` ; do
> dump $file | cut -c9-50 | egrep -m1 -q ' 0d| 0d'
> if [ $? -eq 0 ] ; then echo $file ; fi
> done

Yukarıdakilere yapmak isteyebileceğiniz değişiklikler şunları içerir:

  • sadece taramak istediğiniz dosyaları bulmak için bul komutunu değiştirin
  • değiştirmek dökümü için komut od var ya da her türlü dosya dökümü programı
  • cut komutunun hem baştaki hem de sondaki boşluğu ve ayrıca döküm yardımcı programından yalnızca onaltılık karakter çıktısını içerdiğini onaylayın
  • verimlilik için döküm çıktısını ilk 1000 karakterle sınırlayın

Örneğin, bunun gibi bir şey dump yerine od kullanarak işinize yarayabilir :

 od -t x2 -N 1000 $file | cut -c8- | egrep -m1 -q ' 0d| 0d|0d$'

1

dos2unix dönüştürülecek dosyaları göstermek için kullanılabilecek bir dosya bilgisi seçeneğine sahiptir:

dos2unix -ic /path/to/file

Bunu yinelemeli olarak yapmak için, mevcut kabuk için etkinleştirilen bash's globstarseçeneğini kullanabilirsiniz shopt -s globstar:

dos2unix -ic **      # all files recursively
dos2unix -ic **/file # files called “file” recursively

Alternatif olarak findbunun için kullanabilirsiniz :

find -exec dos2unix -ic {} +            # all files recursively
find -name file -exec dos2unix -ic {} + # files called “file” recursively
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.