web-dev-qa-db-ja.com

ファイルを変更せずにCRLFまたはLFを使用しているかどうかをテストする方法は?

一部のtextファイルがLinuxモードで保持されるようにするコマンドを定期的に実行する必要があります。残念ながらdos2unixは常にファイルを変更します。これにより、ファイルとフォルダーのタイムスタンプが混乱し、不要な書き込みが発生します。

私が書いたスクリプトはBashで書かれているので、Bashに基づいた回答をお勧めします。

53
Adam Ryczkowski

dos2unixをフィルターとして使用して、その出力を元のファイルと比較できます。

dos2unix < myfile.txt | cmp - myfile.txt
44

タイムスタンプへの影響を回避することだけが目的の場合、dos2unix があります -kまたは--keepdateオプションは、タイムスタンプを同じに保ちます。一時ファイルを作成して名前を変更するには、書き込みを行う必要がありますが、タイムスタンプには影響しません。

ファイルの変更が受け入れられない場合は、 this answer から次の解決策を使用できます。

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

あなたはCRLFコードのためにgrepを試すことができます、8進数:

grep -U $'\015' myfile.txt

または16進数:

grep -U $'\x0D' myfile.txt
22
don_crissti

バージョン7.1 dos2unixには-i--infoオプションで改行に関する情報を取得します。 dos2unix自体を使用して、変換が必要なファイルをテストできます。

例:

dos2unix -ic *.txt | xargs dos2unix
22

最初の方法(grep):

復帰を含む行を数えます:

[[ $(grep -c $'\r' myfile.txt) -gt 0 ]] && echo dos

で終わるキャリッジリターンである行を数えます。

[[ $(grep -c $'\r$' myfile.txt) -gt 0 ]] && echo dos

これらは通常同等です。行の内部(つまり、最後ではない)での復帰はまれです。

もっと効率的:

grep -q $'\r' myfile.txt && echo dos

これはより効率的です

  1. カウントをASCII文字列に変換し、その文字列を整数に変換してゼロと比較する必要がないため、
  2. grep -cは、パターン全体の出現をカウントするためにファイル全体を読み取る必要があるため、grep -qは、パターンの最初の出現を検出すると終了できます。

メモ:

  • GNU grepであるため、上記全体を通して、-Uオプションの追加(つまり、-cUまたは-qUを使用)が必要になる場合があります。ファイルがテキストファイルであるかどうかを推測します。ファイルがテキストであると判断した場合、$を定期的に作成しようとして、行末の改行を無視します正規表現は「正しく」機能します—正規表現が\r$!であっても、-U(または--binary)を指定すると、この推測が無効になり、grepは、ファイルをバイナリとして扱い、CR末尾をそのままにして、データをそのまま一致するメカニズムに渡します。
  • grepgrep … $'\r\n' myfile.txtをパターン区切り文字として扱うため、\nを実行しないでください。 grep -E 'foo|'fooまたはnull文字列を含む行を検索するのと同様に、grep $'\r\n'\rまたはnull文字列を含む行を検索し、すべての行がnull文字列と一致します。

2番目の方法(file):

[[ $(file myfile.txt) =~ CRLF ]] && echo dos

fileは次のように報告するためです。

myfile.txt: UTF-8 Unicode text, with CRLF line terminators

より安全なバリアント:

[[ $(file -b - < myfile.txt) =~ CRLF ]] && echo dos

どこ

fileからの出力のチェックは、英語以外のロケールでは機能しない可能性があることに注意してください。

14
BertS

cat -Aを使用

$ cat file
hello
hello

このファイルが* NIXシステムで作成された場合、次のように表示されます。

$ cat -A file
hello$
hello$

しかし、このファイルがWindowsで作成された場合、次のように表示されます。

$ cat -A file
hello^M$
hello

^MCRを表し、$LFを表します。 Windowsが最後の行をCRLFで保存しなかったことに注意してください

これにより、ファイルの内容も変更されません。

14
GypsyCosmonaut

あなたのためのbash関数:

# return 0 (true) if first line ends in CR
isDosFile() {
    [[ $(head -1 "$1") == *$'\r' ]]  
}

次に、次のようなことができます

streamFile () {
    if isDosFile /tmp/foo.txt; then
        sed 's/\r$//' "$1"
    else
        cat "$1"
    fi
}

streamFile /tmp/foo.txt | process_lines_without_CR
4
glenn jackman

ファイルにDOS/WindowsスタイルのCR-LF行末がある場合、Unixベースのツールを使用してそれを見ると、各行の終わりにCR( '\ r')文字が表示されます。

このコマンド:

grep -l '^M$' filename

ファイルにWindowsスタイルの行末を持つ1つ以上の行が含まれている場合はfilenameを出力し、含まれていない場合は何も出力しません。 ^Mはリテラルの復帰文字でなければならないことを除いて、通常は次のように入力して端末に入力します。 Ctrl+V に続く Enter (または Ctrl+V その後 Ctrl+M)。 bashシェルを使用すると、リテラルキャリッジリターンを$'\r'ここに記載 )として記述できるため、次のように記述できます。

grep -l $'\r$' filename

他のシェルも同様の機能を提供します。

代わりに別のツールを使用できます。

awk '/\r$/ { exit(1) }' filename

これは、ファイルにWindowsスタイルの行末が含まれている場合は1のステータス($?1に設定)で終了し、含まれている場合は0のステータスで終了します。シェル、ifステートメントで使用すると便利です([ブラケット]がないことに注意してください):

if awk '/\r$/ { exit(1) }' filename ; then
    echo filename has Unix-style line endings
else
    echo filename has at least one Windows-style line ending
fi

ファイルには、UnixスタイルとWindowsスタイルの行末を混在させることができます。ここでは、anyWindowsスタイルの行末を持つファイルを検出することを想定しています。

4
Keith Thompson

fileを使用:

$ file README.md
README.md: ASCII text, with CRLF line terminators

$ dos2unix README.md
dos2unix: converting file README.md to Unix format...

$ file README.md
README.md: ASCII text
3
Dan Sorak

私は使用しています

cat -v filename.txt | diff - filename.txt

うまくいくようです。私は出力が少し読みやすいと思います

dos2unix < filename.txt | diff - filename.txt

何らかの理由でdos2unixをインストールできない場合にも役立ちます。

2
Alex028502