言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

Haskell で改行コード変換

DOS 形式と UNIX 形式が混在したソースツリーがあって、これを UNIX 形式に統一しよう!と思ったんだけど Google で探しても沢山ありすぎて訳が分からなくなってしまった。なので Haskell で書いてみた。

やりたいこと。

  • dos2unix: in-place で DOS から UNIX に改行コード変換
-- コンパイル方法
-- $ ghc -o dos2unix dos2unix.hs
import System.IO (openTempFile, hClose, hPutStr)
import System.Directory (renameFile)
import System.Environment (getArgs)

単にファイルを読み込んで filter で \r を削除してるだけです。一時ファイルの命名にはもっと凝ったことが出来るようですが、面倒なのでカレントディレクトリに数字で作ってます。

-- DOS -> UNIX 改行変換。変換後元のファイルを書き換えます。
dos2unix :: String -> IO ()
dos2unix input = do src <- readFile input -- ファイルの中身をごそっと読み込むと Haskell がちょっとずつ処理してくれる。
                    let dst = filter (/= '\r') src -- src の中から CR 削除して dst へ
                    (tempfile, temph) <- openTempFile "." "dos2unix" -- 一時ファイルの作成。カレントディレクトリに dos2unixXXX という名前になる。
                    hPutStr temph dst -- 一時ファイルに書き込む
                    hClose temph -- 一時ファイルを閉じる
                    renameFile tempfile input -- 一時ファイルを元のファイル名にリネーム

シェルから呼び出す時に必要な main 関数。

-- 引数があれば dos2unix を実行。無ければ usage を表示
main = do args <- getArgs
          let run (x:_) = dos2unix x
              run _ = putStrLn ("usage: dos2unix filename")
          run args

本当はファイルディレクトリを渡り歩く部分も作ろうと思ったんだけど、時間切れ。ディレクトリ内の c|h ファイルを全部変換するには次のようにします。

find . -name '*.[c|h]' -exec dos2unix {} \;

のようにして使います。gist はこちら。 https://gist.github.com/propella/5291085
sed で書けば一行ですが。たまにコードを書かないと忘れるので。。。