Linuxでgrepを使用してdos行末(CRLF)を含むファイルをどのように検索しますか?


126

Linuxでgrepを使用してdos行末を含むファイルを検索したい。このようなもの:

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

上記はリテラルrnと一致するようですが、これは望ましいことではありません。

この出力は、xargsを介してtodosにパイプされ、このようにcrlfをlfに変換されます

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

2
dos2unixを試しましたか?行末を自動的に修正します。
だらしない2008

よくわかりませんが、「」内のパターンの引用と「」の違いがあります。「エスケープシーケンス」で囲まれたパターン内のAfaikは適切な文字列として解釈されるため、「\ r」は「\\ r」および「 \ R」は「は(少なくともその表記)は相当するものはない。
Anticom

Anticom:この場合、 'と "の違いは関係ありませんが、'囲まれた文字列は弱い引用符で囲まれ、"は強い引用符で囲まれているため、通常は区別されます。私が利用する最大のことは、$展開または ``弱い引用符付き文字列で展開しないことです。詳細については、引用のbash-hackersを参照してください。
bschlueter、2015年

4
最も簡単な方法は、モダンスイッチを使用dos2unixする-icことです。LFファイルの場合、unix2dosで検索でき-icます。ファイルは変更されません。レポートのみ。
ジヴェンコア2017

3
これはLinuxでのWindowsの行末/改行に関するすべての質問に対するトップアンサーであるため、コマンドを使用してターミナルでそれらを確認できること注目に値しますcat -v somefile.txt。彼らは次のように表示されます^M
user5359531

回答:


121

Ctrl+ VCtrl+ Mを使用して、文字通りの復帰文字をgrep文字列に入力します。そう:

grep -IUr --color "^M"

動作します- ^M私が提案したように入力した文字通りのCRがある場合。

ファイルのリストが必要な場合は、-lオプションも追加する必要があります。

説明

  • -I バイナリファイルを無視する
  • -UgrepがCR文字を取り除くのを防ぎます。デフォルトでは、テキストファイルであると判断した場合に実行されます。
  • -r 各ディレクトリの下のすべてのファイルを再帰的に読み取ります。

3
すぐに使えるハックですが、人間のreadbaleソリューションは次のようになると思います:grep $ '\ r' / bash shell only /またはgrepprintf '\r'
akostadinov

5
@akostadinov +1、しかし、バッククォートはコメントから解釈されました;)2番目のオプションは、言い換えればgrep $(printf '\r')です。しかし、bashを含むほとんどの実用的な用途では、私はを使い続け$'\r'ます。
jankes

3
注:このオプション-UはWindows(またはcygwin)にのみ関連しますが、ここでは重要です。Windowsでは、このコマンドがないとコマンドは機能しません。
sleske 2013

3
オプションのポイントは何-Iですか?マニュアルでは、バイナリファイルは一致しないと見なされているようです。-I-U(バイナリタイプを強制する)の組み合わせにより、すべてのファイルが不一致と見なされてはいけませんか?
ジャニスElmeris

3
アドオンオプションとして '-l'フラグについて言及されていますが、質問は基本的にファイルのリストを要求するため、主な回答に含める必要があると思います。また、検索が速くなります。
arr_sea 2015

167

grepはおそらくこれに必要なツールではありません。これは、すべてのファイルで一致するすべての行の行を出力します。たとえば、10行のファイルでtodosを10回実行したい場合を除いて、grepはそのための最良の方法ではありません。ツリー内のすべてのファイルでファイルを実行するためにfindを使用し、それから "CRLF"をgreppingすると、dosスタイルの行末を持つファイルごとに1行の出力が得られます。

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

次のようなものになります:

./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

私はすでにこれを解読しましたが、とにかくありがとう。 grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'
Tim Abell、

5
grepの-lオプションは、各ファイルの一致をリストするのではなく、ファイルをリストする(一度だけ)ように指示します。
pjz 2008

7
fileプログラムの動作(文書化されていない、人間による消費を対象とする)に依存するのは適切な解決策ではありません。これは非常に壊れやすいです。(1つだけ)の例:XMLファイルでfileは機能せXML document textず、改行タイプに関係なくレポートします。
leonbloy 2013年

1
@leonbloy、-m /dev/null私のオプションは小文字のようですfind (GNU findutils) 4.4.2(Ubuntu 12.04)。
EarlCrapstone 2014

7
私はこの答えが一番好きです。私は単純にそうしましたfind . -type f | xargs file | grep CRLF
ブリアンズ

58

11
ありがとう!後に来る人たちを明確にするために、bashマニュアルでは「$ 'string'の形式の単語は特別に扱われます。単語はstringに展開され、バックスラッシュでエスケープされた文字はANSI C規格の指定に従って置き換えられます。」(このサポートされているコードのリストも参照してください)
Sean Gugler

5
これはbash固有ですか?ある場合は注意が必要です。
cubuspl42 2016年

autocrlfがひどいgitの場合、次のように使用します。grep -IUlrZ $ '\ r' | xargs -0 sed -zbi 's / \ r // g'
buzard

16

grepのバージョンが-P(--perl-regexp)オプションをサポートしている場合、

grep -lUP '\r$'

使用することができます。


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

クエリは検索でした...同様の問題があります...誰かがバージョン管理に行末が混在しているので、0x0d 0x0d 0x0a行末のファイルがたくさんあります。ご了承ください

grep -P '\x0d\x0a'

すべての行を検索しますが、

grep -P '\x0d\x0d\x0a'

そして

grep -P '\x0d\x0d'

行が見つからないため、行末パターンに関しては、grep内で何か「その他」が行われている可能性があります...残念ながら私にとっては!


3

UNIXではfileコマンドを使用できます。ファイルの文字エンコードと行末記号を提供します。

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

1

私のように、ミニマリストのunixにfileコマンドのような機能が含まれておらず、grep式のバックスラッシュがうまく機能しない場合は、次のように試してください。

$ 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

上記に加えたい変更には次のものがあります。

  • 検索コマンドを調整して、スキャンするファイルのみを検索します
  • 変更ダンプするコマンドODあなたが持っているか、どんなファイルダンプユーティリティ
  • cutコマンドに、先頭と末尾の両方のスペース、およびダンプユーティリティからの16進文字出力のみが含まれていることを確認します。
  • 効率を上げるために、ダンプ出力を最初の1000文字程度に制限します

たとえば、dumpの代わりにodを使用すると、次のようなものが機能する場合があります。

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

1

dos2unix 変換されるファイルを表示するために使用できるファイル情報オプションがあります。

dos2unix -ic /path/to/file

これを再帰的に行うには、現在のシェルで有効になっているbashglobstarオプションを使用できますshopt -s globstar

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

あるいは、あなたはそれのために使うことができますfind

find -exec dos2unix -ic {} +            # all files recursively
find -name file -exec dos2unix -ic {} + # files called “file” recursively
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.