目次へ戻る §22へ戻る §24へ進む

23. Cygwin 1.7.5

2010/5/21, 2010/6/3 (鈴)

23.1 はじめに

本章では,執筆時現在,現行版である Cygwin 1.7.5 を使うためのいくつかのコツを説明します。 Cygwin 1.7.5 は本格的に locale をサポートしていますが,指定しなければその初期設定は

LANG=C.UTF-8

です。このとき,基本的な locale は "C" であり,メッセージ等には英語が使われますが,文字エンコーディングには UTF-8 が使われます。POSIX の locale とワイドキャラクタのメカニズム全体で UTF-8 がサポートされますから,例えば bash のコマンド行入力で日本語を使うことができます。 Windows の日本語 IME を使っていわゆる全角文字を入力したとき, 全角文字単位で正しくカーソルの移動や文字の挿入・消去が行われます。

20. UTF-8 Cygwin の場合と同じく,日本語版 Windows ならば,コマンドプロンプトの既定のフォント設定のおかげで日本語文字を含むほとんどの Unicode 文字を表示できます。UTF-8 といっても, 標準のコマンドプロンプト以外に何か特別な端末プログラムを用意する必要はさしあたりありません。

6/1 に岩室氏から,既定では East Asian Ambiguous Width Character に対して POSIX 関数 wcwidth, wcswidth が文字幅を 1 とするので,ja_JP.UTF-8 と設定したほうが良い旨,御指摘をいただきました。 矢印 "→" やギリシャ文字 "α" などがこれに該当します。 日本語版 Windows の既定のフォント設定ではこれらは文字幅 2 の全角文字として表示されますから,初期設定のままでは正しく行編集できません。
§21.4 で述べた日本語メッセージ一般の問題は Cygwin 1.7.5 では解決していますが,個々のコマンドに対しては日本語メッセージの常用にまだ若干の不具合と不安があります。 例えば,下記では「月」がありません。 またもしも英語形式の出力を仮定しているスクリプトがあれば,それも動きません。
01:~$ LANG=ja_JP.UTF-8 date
2010年 6  3日 木曜日 17:35:00 JST
01:~$ 

文字の取り扱いだけ ja_JP.UTF-8 (日本国 (JP) における日本語 (ja),エンコーディングは UTF-8,の意) にしたい場合は,環境変数 LC_CTYPEja_JP.UTF-8 とします。 §23.3 を御覧ください。

Cygwin 1.7.7 では「月」が表示されない問題は解決しています。(2010/11/10 追記)

23.2 設定ファイル

「UTF-8 Cygwin - 使用法」の 設定ファイル で説明した設定がそのまま使えます。 ただし,Python 用の sitecustomize.py は不要です。 Python の対話入力で日本語を扱うために us_ascii を utf_8 にすげかえるハッキングはもう要りません。 正攻法で使えます。

日本国内ならば,~/.bash_profile の末尾に

export TZ='Asia/Tokyo'

を追加するとよいでしょう。 date コマンドの出力で "JST" が表示されるようになります。

01:~$ date
Thu May 20 12:34:56 JST 2010
01:~$ 

これは現行版よりもずっと前からあった設定ですが,今まで説明し忘れていました。 §18.2 の出力例で時刻に "JST" が出ているのを不思議に思った人もいたかもしれません。 Asia/Tokyo という値は Cygwin の tzcode パッケージに含まれる /usr/sbin/tzselect から得たものです。

テキストエディタ vim は POSIX の枠組みとは独立に文字コードを処理します。 日本語フォントによる表示では,矢印文字やギリシャ文字などの文字幅計算が狂います。 ですから ~/.vimrc では set ambw=double の設定をしてください。
set encoding=utf-8
set ambw=double
set fileencodings=iso-2022-jp,utf-8,euc-jp,cp932
let $LANG='ja'

Cygwin 1.5.* 以前と異なり,ファイルシステムの mount 情報はもはやレジストリに記録されません (§3.2 参照)。 通常の Unix と同じように,今や mount コマンドに永続的な効果はありません。 独自の設定をする場合は /etc/fstab ファイルを編集します。 ただし,/usr/bin などシステムに必須の mount 操作は,/etc/fstab ファイルに設定がなくても暗黙のうちに行われます。 ですから,/etc/fstab ファイルは,コメント行と空行だけのままにしても差し支えありません。

mount して構成したディレクトリツリーは Cygwin の中だけにある仮想的なものです。 むしろ,mount するのではなく,エクスプローラからショートカットとして使えるシンボリック・リンクを設けたほうが,GUI とコマンドラインの両面から矛盾なくアクセスできて便利です。次節を参照してください。 他のマシンの共有フォルダについても同様です。

01:~$ ls -l Public
lrwxrwxrwx 1 suzuki None 16 2010-04-02 09:02 Public -> //VBOXSVR/Public/
01:~$ 

23.3 Cygwin.bat の改造

Cygwin のルートディレクトリ (Windows から見たとき,デフォルトどおりにインストールした場合は C:\cygwin) にある Cygwin.bat

bash --login -i

の箇所を

set CYGWIN=winsymlinks
set LC_CTYPE=ja_JP.UTF-8
bash --login -i

にします。

環境変数 CYGWINwinsymlinks とセットすることで,(Cygwin 1.5.* の場合と同じように) Cygwin で作るシンボリック・リンクを,Windows のエクスプローラからそのままショートカットとして使えるようにします。 ただし,この設定を行う前に作ったシンボリック・リンクは当然そのまま (ショートカットとして使えないまま) です。

ショートカットとして使えるようにしたシンボリック・リンクは,読み書きが遅いと言われています (The CYGWIN environment variable 参照)。 日常的な操作のなかで遅さに気付くことは無いと思いますが,ベンチマーク・テストをするとき (だけ) は気にした方がよいかもしれません。
環境変数 CYGWIN は Cygwin 全体の振舞に関係しますから,普通は Cygwin.bat かそれ以前の段階で設定します。 しかし,試したところ,少なくとも winsymlinks の設定だけならば,bash の起動後でも,環境変数の値の変更で安全に振舞を切り替えられそうでした。 bash のプロセスそれ自身はシンボリック・リンクを作らず,その都度,子プロセスとして ln -s を実行しますから,これは不思議ではありません。 しかし,ここでは一応,慣例 (?) どおりに Cygwin.bat で設定します。

§23.1 で述べたように,初期設定で文字エンコーディングに UTF-8 が使われますが,日本語フォントによる表示では,矢印文字やギリシャ文字などの文字幅計算が狂います。 環境変数 LC_CTYPEja_JP.UTF-8 として,これを解決します。

環境変数 LC_CTYPELANG は,locale のメカニズムをとおして行編集ライブラリ readline の動作に影響を及ぼします。 しかし,その値が参照されるのは,行編集ライブラリを利用するプログラム (ここでは bash) の起動時です。 したがって,環境変数 TZ のように ~/.bash_profile で設定することはできず, Cygwin.bat を改造する必要があります。

23.4 Mac OS X との相互運用性

ファイル名が同じように UTF-8 で表現されていますから,ちょっと考えると Mac OS X と高い相互運用性があるように思えます。 しかし,実際に Mac OS X で作成された tar アーカイブ等を Cygwin にもってきて展開すると,濁点付きのひらがな,カタカナが化ける現象に悩まされます。 これはファイル名に採用されている Unicode の正規形の違いによるものです。

UTF-8 Cygwin では,この問題を解決するため,「Mac OS X との相互運用性」 で説明したような正規形変換処理を Cygwin 内部に作り込んでいました。

ここでは Cygwin 本体を改造するのではなく,アーカイブを展開した後でディレクトリツリーの ファイル名,フォルダ名をまとめて変換する Python スクリプトを用意して,この問題を解決します。

normalize_file_names.py (1892 バイト)

#!/usr/bin/env python
# -*- coding: utf-8 -*- H22.5/20 (鈴)
"""
ディレクトリツリーにあるファイルおよびディレクトリ名を NFC に正規化する。

ファイル名とディレクトリ名は UTF-8 で表現されていると仮定する。
典型的には,Mac で作成した tar ファイル等を Cygwin で展開した後,
これを使って,ファイル名の濁音・半濁音のかなや字上符付きアルファベット
を Windows で普通に扱える形式にする。
"""

import os, sys, unicodedata

def normalize(s):
    """UTF-8 文字列 s を NFC に正規化した文字列を返す。"""
    u = s.decode('utf-8')
    n = unicodedata.normalize('NFC', u)
    return n.encode('utf-8')


def normalize_file_names_in_list(name_list, dirpath):
    """
    name_list にあるファイル名を正規化する。ディレクトリは dirpath とする。
    実際のファイル名とともに name_list の要素も正規化後の名前に置き換える。
    """
    for (index, old_name) in enumerate(name_list):
        new_name = normalize(old_name)
        if new_name != old_name:
            print '%s: %r -> %s' % (dirpath, old_name, new_name)
            old_path = os.path.join(dirpath, old_name)
            new_path = os.path.join(dirpath, new_name)
            os.rename(old_path, new_path)
            name_list[index] = new_name

def normalize_file_names(top):
    """ディレクトリ top の下にある UTF-8 ファイル名を NFC に正規化する。"""
    for (dirpath, dirnames, filenames) in os.walk(top):
        normalize_file_names_in_list(dirnames, dirpath)
        normalize_file_names_in_list(filenames, dirpath)

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print >> sys.stderr, "usage: %s directory" % (sys.argv[0])
        sys.exit(1)
    top = sys.argv[1]
    normalize_file_names(top)

このスクリプトはコマンド行引数を1個とります。 引数をディレクトリの名前として,そのディレクトリの下にあるファイル名,ディレクトリ名をすべて NFC に正規化します。 Windows は普通は NFC 正規形の Unicode でファイル名をファイルシステムに格納し, Cygwin はそれを単純に UTF-8 に変換して私たちに見せていることに注意してください。 下記はスクリプトの使用例です。

ちなみに,Cygwin で作成したアーカイブを Mac OS X で展開するときは,自動的に逆変換されますから正規形の問題はありません。

目次へ戻る §22へ戻る §24へ進む

Copyright (c) 2010 OKI Software Co., Ltd.