BashスクリプトでDOS / Windows改行(CRLF)をUnix改行(LF)に変換する方法は?


336

プログラムで(つまりを使用せずにvi)DOS / Windowsの改行をUnixに変換するにはどうすればよいですか?

dos2unixそしてunix2dosコマンドは、特定のシステムでは使用できません。どのように私はこれらのようなコマンドをエミュレートすることができますかsed/ awk/ tr


9
一般に、dos2unixパッケージマネージャーを使用してインストールするだけです。これは非常に簡単で、ほとんどのプラットフォームに存在します。
Brad Koch、

1
同意しました!@BradKoch Mac OSXで「brew install dos2unix」としてシンプル
SmileIT

回答:


322

trDOSからUnixへの変換に使用できます。ただし、CRがファイルにCRLFバイトペアの最初のバイトとしてのみ表示される場合にのみ、これを安全に行うことができます。これは通常のケースです。次に使用します:

tr -d '\015' <DOS-file >UNIX-file

名前DOS-fileは名前とは異なることに注意してくださいUNIX-file。同じ名前を2回使用しようとすると、ファイルにデータがなくなります。

他の方法でそれを行うことはできません(標準の 'tr'を使用)。

あなたがスクリプトにキャリッジリターンを入力する方法を知っていれば(control-Vcontrol-Mその後、制御-Mを入力します):

sed 's/^M$//'     # DOS to Unix
sed 's/$/^M/'     # Unix to DOS

ここで、「^ M」はコントロールM文字です。bash ANSI-C引用メカニズムを使用して、復帰を指定することもできます。

sed $'s/\r$//'     # DOS to Unix
sed $'s/$/\r/'     # Unix to DOS

あなたは非常に頻繁にこれを実行する必要があるとしている場合は、(複数回、大まかに言えば)、変換プログラムをインストールするには、はるかに賢明である(例えばdos2unix、およびunix2dos、またはおそらくdtouutod)とそれらを使用しています。

ディレクトリとサブディレクトリ全体を処理する必要がある場合は、次を使用できますzip

zip -r -ll zipfile.zip somedir/
unzip zipfile.zip

これにより、行末がCRLFからCRに変更されたzipアーカイブが作成されます。unzip次に、変換されたファイルを元の場所に戻します(ファイルごとに尋ねます-答えは「はい」から「すべて」)。これを指摘してくれた@vmsnomadの功績。


9
tr -d '\015' <DOS-file >UNIX-filewhere DOS-file== を使用するUNIX-fileと、空のファイルになります。残念ながら、出力ファイルは別のファイルでなければなりません。
Buttle Butkus 2013年

3
@ButtleButkus:そうですね。そのため、2つの異なる名前を使用しました。プログラムがすべてを読み取る前に入力ファイルを消去すると、同じ名前を2回使用するときのように、空のファイルになります。これは、Unixライクなシステムでの均一な動作です。入力ファイルの上書きを安全に処理するには、特別なコードが必要です。指示に従ってください、あなたは大丈夫です。
ジョナサンレフラー2013年

ファイル内の検索置換機能を覚えているようです。
Buttle Butkus 2013年

4
場所があります。それらを見つける場所を知っている必要があります。制限内では、GNU sedオプション-i(インプレース用)が機能します。制限はリンクされたファイルとシンボリックリンクです。sortコマンドはいつも'(1979年以来、そうでない場合は、以前の)サポートしてきた-o入力ファイルのいずれかを一覧表示することができますオプションを選択します。ただし、sort出力を書き込む前にすべての入力を読み取る必要があるためです。他のプログラムは、入力ファイルの1つを上書きすることを散発的にサポートします。Kernighan&Pikeによる「UNIXプログラミング環境」で問題を回避するための汎用プログラム(スクリプト)を見つけることができます。
ジョナサンレフラー、2013年

3
おかげで、3番目のオプションはうまくいきました。私は-iオプションを使用しました:sed -i $'s/\r$//' filename- その 場で編集します。インターネットにアクセスできないマシンで作業しているため、ソフトウェアのインストールに問題があります。
Warren Dew

64
tr -d "\r" < file

使用例については、こちらご覧くださいsed

# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//'               # assumes that all lines end with CR/LF
sed 's/^M$//'              # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//'            # works on ssed, gsed 3.02.80 or higher

# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\\r`/"            # command line under ksh
sed 's/$'"/`echo \\\r`/"             # command line under bash
sed "s/$/`echo \\\r`/"               # command line under zsh
sed 's/$/\r/'                        # gsed 3.02.80 or higher

sed -iインプレース変換などに使用しsed -i 's/..../' fileます。


10
私のファイルには次のものしかなかったので、私はバリアントを使用しました\rtr "\r" "\n" < infile > outfile
Matt Todd

1
@MattTodd回答として投稿していただけませんか?これ-dはより頻繁に取り上げられ、「唯一の\r」状況では役に立ちません。
n611x007 2013年

5
提案さ\rれた\nマッピングにはファイルのダブルスペースの効果があることに注意してください。DOSで終わる各CRLF行\n\nはUnixになります。
ジョナサンレフラー2014

これを再帰的に実行できますか?
アーロンフランケ

36

POSIXでこれを行うのは注意が必要です。

  • POSIX Sed\rまたはをサポートしていません\15。たとえあったとしても、その場でのオプション-iはPOSIXではありません

  • POSIX Awk\rおよびをサポートし\15てい-i inplaceますが、オプションはPOSIXではありません

  • d2udos2unixPOSIXユーティリティではありませんが、ex

  • POSIX exはサポートしていない\r\15\nまたは\12

改行を削除するには:

ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file

改行を追加するには:

ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file

2
POSIXがtrサポートしている\rようです。 したがってprintf '%s\n' '%!tr -d "\r"' x | ex file、使用することもできます(当然ですが、\r直前のでなくても削除され\nます)。また、-bオプションexはPOSIXでは指定されていません。
ワイルドカード

1
POSIXでこれを行うのは簡単です。CRリテラルを入力してスクリプトに埋め込みます(control-Mです)。
ジョシュア

28

オプション-c {command}を使用してプログラムでvimを使用できます。

UnixへのDos:

vim file.txt -c "set ff=unix" -c ":wq"

Unixからdos:

vim file.txt -c "set ff=dos" -c ":wq"

「set ff = unix / dos」は、ファイルのファイル形式(ff)をUnix / DOSの行末形式に変更することを意味します

":wq"は、ファイルをディスクに書き込み、エディターを終了します(ループでコマンドを使用できます)


3
これは最も洗練されたソリューションのように見えましたが、wqの意味についての説明がないのは残念です。
ジョリックスレイスター

4
使用viする人は誰でもその:wq意味を知っています。3文字でない場合、1)viコマンド領域を開く、2)書き込む、3)終了するという意味です。
David Newcomb

CLIからvimにインタラクティブにコマンドを追加できるとは思いませんでした
Robert Dundon

「:wq」の代わりに「:x」を使用できます
JosephConrad

25

AWKを使用すると、次のことができます。

awk '{ sub("\r$", ""); print }' dos.txt > unix.txt

Perlを使用すると、次のことができます。

perl -pe 's/\r$//' < dos.txt > unix.txt

2
ポータブル優れたawkソリューション。
mklement0 2015

23

ファイルをその場で変換するには

dos2unix <filename>

変換されたテキストを別のファイルに出力するには

dos2unix -n <input-file> <output-file>

UbuntuまたはDebianにインストールできます

sudo apt install dos2unix

またはmacbでhomebrewを使用

brew install dos2unix

1
私は質問がdos2unixの代わりを求めることを知っていますが、それは最初のグーグルの結果です。
ボリス

18

この問題は標準ツールで解決できますflipが、20年以上前にの作者であるRahul Dhesiが作成したコマンドをインストールすることをお勧めしますzoo。たとえば、バイナリファイルの不注意による破壊を回避しながら、ファイル形式を変換する優れた仕事をします。これは、目にするすべてのCRLFの変更に取り掛かるだけでは少し簡単です...


元のファイルを変更せずに、ストリーミング形式でこれを行う方法はありますか?
augurar 2013

@augurarで「類似パッケージ」を確認できますpackages.debian.org/wheezy/flip
n611x007 '19

間違ったフラグでtexxtoを実行するだけで、OSの半分が壊れるという経験がありました。フォルダ全体で実行する場合は特に注意してください。
A_P 2018

14

これまでに投稿された解決策は問題の一部のみを扱い、DOS / WindowsのCRLFをUnixのLFに変換します。欠けているのは、DOSがCRLFを行区切り文字として使用するのに対し、UnixはLFを行終了文字として使用することです。違いは、DOSファイル(通常)はファイルの最後の行の後に何もないことですが、Unixにはあります。正しく変換するには、その最後のLFを追加する必要があります(ファイルの長さがゼロでない場合、つまりファイルに行がない場合を除きます)。これに対する私のお気に入りの呪文(Mac形式のCRで区切られたファイルを処理するためのロジックが少し追加され、すでにUNIX形式の痴漢ファイルではない)は少しperlです。

perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt

これにより、Unix化されたバージョンのファイルがstdoutに送信されることに注意してください。ファイルをUnix化されたバージョンに置き換える場合は、perlの-iフラグを追加します。


@LudovicZenohateLagouardetteこれはプレーンテキストファイル(つまり、csvまたはタブ送信テキスト)でしたか、それとも他の何かですか?データベースのような形式の場合、テキストのように操作すると、内部構造が破損する可能性が非常に高くなります。
Gordon Davisson 2016年

プレーンテキストのcsvですが、コード化は奇妙だったと思います。そのせいでめちゃくちゃだと思います。しかし、心配しないでください。私は常にバックアップを収集していますが、これは実際のデータセットでもなく、1GBのデータセットでした。本物は26GBです。
Ludovic Zenohate Lagouardette 2016年

14

dos2unixにアクセスできないが、このページを読むことができる場合は、ここからdos2unix.pyをコピーして貼り付けることができます。

#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys

if len(sys.argv[1:]) != 2:
  sys.exit(__doc__)

content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
  content = infile.read()
with open(sys.argv[2], 'wb') as output:
  for line in content.splitlines():
    outsize += len(line) + 1
    output.write(line + '\n')

print("Done. Saved %s bytes." % (len(content)-outsize))

スーパーユーザーからのクロスポスト。


1
使い方は誤解を招くものです。リアルはデフォルトですべての入力ファイルをdos2unix変換します。使用法はパラメータを意味します。そして本当のは、ファイルが与えられない場合、標準入力から読み取り、標準出力に書き込むフィルターです。-ndos2unix
jfs 2015

8

PCREで簡単にスーパーデューパー。

スクリプトとして、または$@ファイルに置き換えます。

#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@

これでファイルが上書きされます!

これはバックアップ(バージョン管理など)でのみ行うことをお勧めします


ありがとうございました!これは機能しますが、ファイル名を書き込んでいますが、はありません--。このソリューションを選択した理由は、理解しやすく、自分に適応しやすいからです。参考までに、これはスイッチの機能です。-p「while入力」ループを想定し、-i入力ファイルを編集して、-e次のコマンドを実行します
Rolf

厳密に言えば、PCREはPerlの正規表現エンジンの再実装であり、Perlの正規表現エンジンではありません。名前に暗示があるにもかかわらず、両者にはこの機能がありますが、違いもあります。
tripleee 2017年

6

プログラムなしのさらに単純なawkソリューション:

awk -v ORS='\r\n' '1' unix.txt > dos.txt

技術的には「1」はプログラムです。b/ c awkはオプションが指定されたときに1つ必要です。

更新:このページを久しぶりに再訪した後、内部ソリューションをまだ誰も投稿していないことに気づきました。

while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt

これは便利ですが、明確にする必要があります。これは、Unix-> Windows / DOSを変換します。これは、OPが要求したものとは逆の方向です。
mklement0 2015

5
それは作者の演習として残された、意図的に行われました。 アイロール awk -v RS='\r\n' '1' dos.txt > unix.txt
nawK

すばらしい(そして教育的技巧についてあなたに称賛する)。
mklement0

1
「b / c awkはオプションが与えられたときに1つ必要です。」-awk は、オプションが指定されているかどうかにかかわらず、常にプログラムを必要とします。
mklement0 2015年

1
純粋なbashソリューションは興味深いものですが、同等のソリューションawksedソリューションよりもはるかに低速です。また、を使用while IFS= read -r lineして入力行を忠実に保存する必要があります。そうしないと、先頭と末尾の空白が削除されます(または、readコマンドで変数名を使用せずにを使用します$REPLY)。
mklement0 2015年

5

おもしろいことに、私のgit-bashのWindows sed ""では、既にトリックが行われています。

$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text

私の推測では、sedは入力から行を読み取るときにそれらを無視し、常に出力にUNIXの行末を書き込みます。


4

これは私のために働いた

tr "\r" "\n" < sampledata.csv > sampledata2.csv 

9
これは、すべての変換されますシングルにDOS-改行を2 UNIX、改行。
Melebius

4

同じ質問を熟考する必要がありました(Windows側ですが、Linuxにも同様に当てはまります)。驚いたことに、古き良きzip -llオプション(Info-ZIP)を使用してテキストファイルのCRLF <-> LF変換を行う非常に自動化された方法については誰も言及していません。

zip -ll textfiles-lf.zip files-with-crlf-eol.*
unzip textfiles-lf.zip 

注:これにより、元のファイル名を保持しながら、行末をLFに変換するzipファイルが作成されます。次にunzip、zipされたファイル、つまり元の名前(ただしLFで終わるファイル)を抽出し、ローカルの元のファイルがある場合は上書きするように求めます。

からの関連抜粋zip --help

zip --help
...
-l   convert LF to CR LF (-ll CR LF to LF)

私によると、ディレクトリ全体とサブディレクトリ全体を処理できるため、ベストアンサーです。そんなに掘り下げてよかったです。
CARAM

2

Mac OSXの場合、homebrewがインストールされている場合[ http://brew.sh/][1]

brew install dos2unix

for csv in *.csv; do dos2unix -c mac ${csv}; done;

このコマンドはファイルを適切に変更するため、ファイルのコピーを作成したことを確認してください。-c macオプションは、スイッチをosxと互換性があるようにします。


この回答は、元の投稿者の質問には当てはまりません。
hlin117 2015

2
OS Xユーザーはを使用しないでください-c mac。これは、OS X CR以前のみの改行を変換するためのものです。このモードは、Mac OS 9以前との間のファイルにのみ使用します。
askewchan 2016

2

TIMTOWTDI!

perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt

@GordonDavissonに基づく

の可能性を考慮する必要があり[noeol]ます...


2

awkを使用できます。レコード区切り文字(RS)を、可能なすべての改行文字または文字と一致する正規表現に設定します。そして、出力レコード区切り文字(ORS)をUNIXスタイルの改行文字に設定します。

awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt

それは私のために働いたものです(MacOS、git diffvimで編集された^ Mを示します)
Dorian

2

Linuxでは、sedを使用して^ M(ctrl-M)を* nix改行(^ J)に変換するのは簡単です。

CLIでは次のようになります。実際にはテキストに改行があります。ただし、\は^ Jをsedに渡します。

sed 's/^M/\
/g' < ffmpeg.log > new.log

入力するには、^ V(Ctrl-V)、^ M(Ctrl-M)、および\(バックスラッシュ)を使用してこれを取得します。

sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log

これは私のために働いたものです、ありがとう!
Dan Mantyla

2
sed --expression='s/\r\n/\n/g'

質問はsedについて言及しているため、これはsedを使用してこれを達成する最も簡単な方法です。この表現では、キャリッジリターンとラインフィードをすべてラインフィードのみに置き換えています。これは、WindowsからUnixに移行するときに必要です。動作することを確認しました。


ジョンポール、この回答は削除のフラグが付けられたので、レビューキューに入れられました。一般に、このような8歳で22の回答がある質問がある場合、他の既存の回答では役に立たない方法で、回答がどのように役立つかを説明する必要があります。
zzxyz 2018年

0

Jonathan LefflerのUnixからDOSへのソリューションの拡張機能として、ファイルの現在の行末がわからない場合に安全にDOSに変換するには:

sed '/^M$/! s/$/^M/'

これは、CRLFに変換する前に、行がCRLFで終わっていないことを確認します。


0

受け入れられた回答に基づいてスクリプトを作成しました。最後に追加のファイルを必要とせず、後で削除して名前を変更することなく、直接変換できます。

convert-crlf-to-lf() {
    file="$1"
    tr -d '\015' <"$file" >"$file"2
    rm -rf "$file"
    mv "$file"2 "$file"
}

「file1.txt」のようなファイルがあり、「file1.txt2」がまだ存在しないか、上書きされることを確認してください。ファイルを一時的に保存する場所として使用します。


0

bash 4.2以降では、次のようなものを使用して、bashビルトインのみを使用する末尾のCRを削除できます。

if [[ "${str: -1}" == $'\r' ]]; then
    str="${str:: -1}"
fi

-3

OSXおよび他のいくつかの方法でsed 's / ^ M $ //' file.txtを試しました(http://www.thingy-ma-jig.co.uk/blog/25-11-2010/fixing- dos-line-endingsまたはhttp://hintsforums.macworld.com/archive/index.php/t-125.html)。何も動作せず、ファイルは変更されませんでした(^ Mを再現するにはCtrl-v Enterが必要でした)。結局、TextWranglerを使用しました。厳密にはコマンドラインではありませんが、機能し、文句を言うことはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.