1. 概要

Linuxでは、キャリッジリターンとラインフィード(CRLF)で終わるファイルは、処理時に問題を引き起こす可能性があります。

このチュートリアルでは、これらのファイルを検索し、行末をLFに変換する方法を学習します。

2. サンプルファイルの作成

まず、戦略をテストするための一連のサンプルファイルを作成しましょう。

$ mkdir -p /tmp/test_folder

これで、テストフォルダを作成しました。 それぞれCRLFとLFで終わる2つのファイルで埋めましょう。

$ printf "Hi \r\n" | tee /tmp/test_folder/crlf_ending{1,2}
Hi
 $ printf "Hi \n" | tee /tmp/test_folder/lf_ending{1,2}
Hi

最初のワンライナーでは、crlf_ending1crlf_ending2という2つのファイルを作成しました。 両方のファイルに「Hi」というメッセージが表示され、その後にで終わるCRLF行が続きます。

2つ目は、同じものにしましたが、LF行の終わりとそれぞれのファイル名を使用しています。

3. CRLFで終わるファイルの検索

Linuxコマンドを使用してCRLFで終わるファイルを見つける方法はいくつかあります。

3.1.

猫コマンドから始めましょう:

$ cat -A /tmp/test_folder/{crlf_ending1,lf_ending1}
Hi ^M$
Hi $

ここで、 catに非印刷文字を表示させる-Aパラメーターを使用すると、両方のファイルの違いを確認できます

3.2. grep

それでは、grepコマンドを試してみましょう。

$ grep -rIl -m 1 $'\r' /tmp/test_folder/
/tmp/test_folder/crlf_ending2
/tmp/test_folder/crlf_ending1

引数を見てみましょう:

  • -r 、フォルダー全体を再帰的に読み取る
  • -I 、バイナリファイルを無視します
  • -l、は、一致するファイルの名前のみを出力します
  • -m 1 、最初の一致後に読み取りを停止します

3.3.  ファイル

さらに、fileコマンドを使用して情報を抽出できます

$ file /tmp/test_folder/*
/tmp/test_folder/crlf_ending1: ASCII text, with CRLF line terminators
/tmp/test_folder/crlf_ending2: ASCII text, with CRLF line terminators
/tmp/test_folder/lf_ending1:   ASCII text
/tmp/test_folder/lf_ending2:   ASCII text

3.4. dos2unix

dos2unixコマンドは、このタスクを実現するための優れたツールですが、すべてのLinuxディストリビューションに常にインストールされているわけではありません。

Debianベースのシステムにインストールするには、次のように入力します。

$ sudo apt-get install dos2unix

次に、行末に関する情報を取得するために、-iパラメーターに含まれている優れた機能を使用してみましょう。

$ dos2unix -i /tmp/test_folder/*
       1       0       0  no_bom    text    /tmp/test_folder/crlf_ending1
       1       0       0  no_bom    text    /tmp/test_folder/crlf_ending2
       0       1       0  no_bom    text    /tmp/test_folder/lf_ending1
       0       1       0  no_bom    text    /tmp/test_folder/lf_ending2

ここで、1列目と2列目には、それぞれDOSとUnixの改行の数が表示されます。

4. CRLFをLFに変換する

CRLF行末のファイルを識別する方法を学習したので、いくつかのツールを使用してCRLFをLFに変換してみましょう。

4.1. sedコマンド

sedコマンドは、テキスト処理に最適なツールです。 これを使用して、crlf_ending1ファイルの行末を見つけて置き換えましょう。

$ sed 's/\r//' /tmp/test_folder/crlf_ending1 | cat -A -
Hi $

この例では、sedコマンドの/\r //’を使用して、 \r文字を検索して空の値に置き換えています。

さらに、ファイルをインラインで編集する場合は、-iパラメーターを使用できます。

最後に、 cat コマンドを使用すると、 ^M文字なしで最終出力を確認できます。

4.2. trコマンド

trコマンドは、文字を削除または翻訳できるシンプルで強力なツールです

パラメータ-dを使用して、 \r文字を削除してみましょう。

$ tr -d '\r' < /tmp/test_folder/crlf_ending1 | cat -A -
Hi $

4.3. awkツール

また、awkツールを使用して\r文字を削除できます。

$ awk 'gsub(/\r/,"")' /tmp/test_folder/crlf_ending1 | cat -A -
Hi $

ここでは、gsub関数を使用して置換を行っています。 次に、アクションを省略することにより、awkは置換を使用してレコード全体を出力します。

4.4. Perl

sed のシナリオのように、Perlインタープリターを使用することもできます。

$ perl -pe 's/\r//' /tmp/test_folder/crlf_ending1 | cat -A -
Hi $

パラメータを詳しく見てみましょう。

  • -p 、各行を読み取るため
  • -e’s / \ r //’ \r文字を削除するスクリプトを入力します

4.5. dos2unix

繰り返しになりますが、dos2unixツールを使用して物事をシンプルに保つことができます

それでは、サンプルファイルで使用してみましょう。

$ dos2unix /tmp/test_folder/crlf_ending1
dos2unix: converting file /tmp/test_folder/crlf_ending1 to Unix format...

ファイルの内容を見てみましょう。

$ cat -A /tmp/test_folder/crlf_ending1
Hi $

CRLF行末がLFに変換されていることがわかります。

最後に、ファイルを復元しましょう。

$ unix2dos /tmp/test_folder/crlf_ending1
unix2dos: converting file /tmp/test_folder/crlf_ending1 to DOS format..

最後に、変換されたコンテンツのみを表示したいが、実際にはファイルを変更しない場合は、リダイレクトを使用できます。

$ dos2unix < /tmp/test_folder/crlf_ending1 | cat - -A
Hi $

4.6. 再コード化

recode は、文字セット間でファイルを変換する興味深いツールです。

私たちのファイルでそれを使用しましょう:

$ recode CP1252...UTF-8 /tmp/test_folder/crlf_ending1

ここでは、ファイルをCP1252(またはWindows-1252)エンコーディングからUTF-8に変換しました。

それでは、内容を見てみましょう。

$ cat -A /tmp/test_folder/crlf_ending1
Hi $

最後に、ファイルを以前のエンコーディングに変換しましょう。

$ recode UTF-8...CP1252 /tmp/test_folder/crlf_ending1

4.7. Vimエディターの使用

vim を使用してCRLF行末をLFに変換するには、ファイルを開きます。

$ vim /tmp/test_folder/crlf_ending1

これで、ESC +「:」と入力してコマンドモードに入ることができます。

次に、 set ff = unix と入力して、Enterキーを押します。

最後に、ESC + ZZ を押して終了し、ファイルを保存しましょう。

内容を見てみましょう:

$ cat -A /tmp/test_folder/crlf_ending1
Hi $

ファイルを回復するには、前の手順を繰り返すことができますが、代わりに set ff =dosと入力します。

4.8. Bashビルトインの使用

最後に、いくつかのbashビルトインを使用して、行末を変換しましょう

$ while read line
do 
    echo "${line/$'\r'/}"
done < /tmp/test_folder/crlf_ending1 | cat -A

結果として、次のようになります。

Hi $

このシナリオでは、whileループにテストファイルをフィードしました。 次に、パラメータ展開を使用して\r文字を削除しました。

5. ファイルの検索と変換を同時に行う

CRLF行末のファイルを見つけてLFに変換する方法がわかったので、これらの操作を組み合わせることができます。

まず、ファイルの検索を回避し、代わりにdos2unixやsedなどのコマンドをフォルダー全体またはパターンに直接適用できます。

$ dos2unix /tmp/test_folder/crlf_ending*
dos2unix: converting file /tmp/test_folder/crlf_ending1 to Unix format...
dos2unix: converting file /tmp/test_folder/crlf_ending2 to Unix format...

sedの場合:

$ sed -i 's/\r//' /tmp/test_folder/crlf_ending*

ただし、 CRLFで終わるファイルのみを変換する場合は、xargsコマンドを使用していくつかのツールを組み合わせることができます。

$ grep -rIl -m 1 $'\r' /tmp/test_folder/ | xargs -P0 -I {} dos2unix {}

別の組み合わせを使用してみましょう:

$ file /tmp/test_folder/* \
    | awk -F : '/CRLF/ && $0=$1' \
    | xargs -P0 -I {} sed -i 's/\r//' {} 

ここでは、 awk を使用して、CRLFエンディングのみを含む各ファイルの名前のみを一覧表示しています。

6. 結論

この記事では、CRLF行末のファイルを識別する方法を学びました。

次に、行末をCRLFからLFに変換する方法を確認しました。

そして最後に、これらの戦略を組み合わせて、ワンライナーでファイルを見つけて変換します。