web-dev-qa-db-ja.com

sshを介して異なるエンコーディングでファイル名を操作する

私は、ファイル名(およびユーザーのロケール)に異なるエンコーディングが使用されているリモートシステムにsshしています。そして、これはいくつかの問題を引き起こします。

ロケール設定を一致させることで解決される問題

ファイル名の問題に移る前に、そのようなsshセッションでのいくつかのエンコーディングの問題 ローカルロケールと一致するようにリモートロケールを設定することで解決されます 、つまり、

  • コマンドラインの編集に関する問題(Backspace triceを押しましたが、ホストではエンコーディングがUTF-8であり、リモートエンドではKOI8-R、またはおそらくCP1251、一部の8ビットキリル文字エンコーディングであるため、これは行われませんでした。 tキリル文字に正しく影響します):

[imz@localhost ~]$ locale
LANG=ru_RU.UTF-8
LC_CTYPE="ru_RU.UTF-8"
LC_NUMERIC="ru_RU.UTF-8"
LC_TIME="ru_RU.UTF-8"
LC_COLLATE="ru_RU.UTF-8"
LC_MONETARY="ru_RU.UTF-8"
LC_MESSAGES="ru_RU.UTF-8"
LC_PAPER="ru_RU.UTF-8"
LC_NAME="ru_RU.UTF-8"
LC_ADDRESS="ru_RU.UTF-8"
LC_TELEPHONE="ru_RU.UTF-8"
LC_MEASUREMENT="ru_RU.UTF-8"
LC_IDENTIFICATION="ru_RU.UTF-8"
LC_ALL=
[imz@localhost ~]$ echo привет
привет
[imz@localhost ~]$ echo при
при
[imz@localhost ~]$ ssh -vv [email protected]
Last login: Fri Nov 25 13:44:56 2011 from NN.NN.NN.NN
[ivan@Dell ~]$ locale
LANG=ru_RU.KOI8-R
LC_CTYPE="ru_RU.KOI8-R"
LC_NUMERIC="ru_RU.KOI8-R"
LC_TIME="ru_RU.KOI8-R"
LC_COLLATE="ru_RU.KOI8-R"
LC_MONETARY="ru_RU.KOI8-R"
LC_MESSAGES=POSIX
LC_PAPER="ru_RU.KOI8-R"
LC_NAME="ru_RU.KOI8-R"
LC_ADDRESS="ru_RU.KOI8-R"
LC_TELEPHONE="ru_RU.KOI8-R"
LC_MEASUREMENT="ru_RU.KOI8-R"
LC_IDENTIFICATION="ru_RU.KOI8-R"
LC_ALL=
[ivan@Dell ~]$ echo привет
привет
[ivan@Dell ~]$ echo при   
привÐ
[ivan@Dell ~]$ export LANG=ru_RU.UTF-8
[ivan@Dell ~]$ echo привет
привет
[ivan@Dell ~]$ echo при
при
[ivan@Dell ~]$ 
  • 処理される文字列の大文字と小文字を区別しないという正しい理解の問題。ロケールを設定した後、これで機能します。

[ivan@Dell ~]$ echo привет | fgrep -i ВЕТ
привет
[ivan@Dell ~]$ 

しかし、これは以前は機能しませんでした。

ファイル名に関する軽微な問題

ファイル名を印刷するユーティリティ(覚えているように、リモートで別のエンコーディングで格納されています)は、そのままでは印刷しませんが、外国語の文字に疑問符を付けます。

[ivan@Dell ~]$ find ~mama/Desktop/ -iname '*.xls'
/home/mama/Desktop/????????? ????????.xls
/home/mama/Desktop/???????? ??? ???????????? (1).xls
/home/mama/Desktop/???????? ??? ???????????? (2).xls
/home/mama/Desktop/???????? ??? ???????????? (3).xls
/home/mama/Desktop/???????? ??? ????????????.xls
[ivan@Dell ~]$ find ~mama/Desktop/ -iname '*.xls' -print
/home/mama/Desktop/????????? ????????.xls
/home/mama/Desktop/???????? ??? ???????????? (1).xls
/home/mama/Desktop/???????? ??? ???????????? (2).xls
/home/mama/Desktop/???????? ??? ???????????? (3).xls
/home/mama/Desktop/???????? ??? ????????????.xls
[ivan@Dell ~]$ 

同じ問題がlsなどでも発生します。しかし、これを文字列として印刷コマンドに渡すことで簡単に克服できます(ファイル名と端末のエンコーディングが一致しないという問題を認識していません-または何らかの理由で動作します)。

[ivan@Dell ~]$ find ~mama/Desktop/ -iname '*.xls' -print0 | xargs -0 -n 1 echo 
/home/mama/Desktop/Êðåäèòíûé ïîðòôåëü.xls
/home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (1).xls
/home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (2).xls
/home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (3).xls
/home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé.xls
[ivan@Dell ~]$ 

また、コマンドの最後に| recode -f cp1251..utf-8を常に追加できるので、それらが判読不能であることはそれほど煩わしくありませんでした。

厄介な問題

本質的な問題は、ターミナルでファイル名を(マウスで)選択して貼り付けることができないことです。

[ivan@Dell ~]$ diff '/home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (1).xls' '/home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (3).xls'
diff: /home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (1).xls: No such file or directory
diff: /home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (3).xls: No such file or directory
[ivan@Dell ~]$ 

statの出力でファイル名のエスケープ表現に気づいたので、それを選択して貼り付けることができました($''bash)::

[ivan@Dell ~]$ diff '/home/mama/Desktop/\300\304\320\305\321\300\322\333 \344\353\377 \357\356\347\344\360\340\342\353\345\355\350\351 (1).xls' '/home/mama/Desktop/\300\304\320\305\321\300\322\333 \344\353\377 \357\356\347\344\360\340\342\353\345\355\350\351 (3).xls'
diff: /home/mama/Desktop/\300\304\320\305\321\300\322\333 \344\353\377 \357\356\347\344\360\340\342\353\345\355\350\351 (1).xls: No such file or directory
diff: /home/mama/Desktop/\300\304\320\305\321\300\322\333 \344\353\377 \357\356\347\344\360\340\342\353\345\355\350\351 (3).xls: No such file or directory
[ivan@Dell ~]$ diff $'/home/mama/Desktop/\300\304\320\305\321\300\322\333 \344\353\377 \357\356\347\344\360\340\342\353\345\355\350\351 (1).xls' $'/home/mama/Desktop/\300\304\320\305\321\300\322\333 \344\353\377 \357\356\347\344\360\340\342\353\345\355\350\351 (3).xls'
Files /home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (1).xls and /home/mama/Desktop/ÀÄÐÅÑÀÒÛ äëÿ ïîçäðàâëåíèé (3).xls differ
[ivan@Dell ~]$ 

だから、問題は:

異なるエンコーディングのリモートファイル名(sshを超える)を簡単に操作するにはどうすればよいですか?

それらが読み取り可能で、選択可能で貼り付け可能である(そして、キーボードから私が入力でき、bashのタブで入力可能である場合、私が便利に入力できると便利です。もちろん、読み取り可能でなければなりません)。

LinuxX.orgurxvtで作業していますローカルホストであり、リモートエンドのLinuxではbashです。

おそらく、文字を翻訳する screen (どちらかの端)のようないくつかの複雑なターミナルエミュレータの使用を検討するかもしれません(または ssh ...)、またはconvmvfs view of the filesystem =リモート(ファイル名はローカルエンコーディングに再コード化されています)ですが、簡単な解決策があります。

ローカルホスト上で、そのリモートホストを操作するための特別な「環境」を作成し、この環境(sshを実行するなど)で作業します。つまり、リモートファイル名がCP1251にある場合は、開始a [〜#〜] x [〜#〜] の新しいターミナルで、そのエンコーディングで機能します

$ LC_CTYPE=ru_RU.CP1251 xvt &

そしてそれから働きます。 (XよりもLinuxコンソールが好きな場合は、それに応じて仮想Linuxコンソールをセットアップすることもできますが、Linuxコンソールのセットアップに関する知識は頭から離れています...)

UTF-8をサポートする端末エミュレーター内で、 luit コマンドを使用して、別のロケールでサブシェル(または他のプログラム)を実行できます。文字セットを示すロケール設定はLC_CTYPE

LC_CTYPE=ru_RU.KOI8-R luit ls   # run one command
LC_CTYPE=ru_RU.KOI8-R luit      # start a Shell (type Ctrl+D or exit to return to the parent Shell)

異なるエンコーディングのファイルのツリー全体がある場合は、(可能であれば) convmvfs を介してマウントすることをお勧めします。

mkdir ~/net/[email protected] ~/net/[email protected]
sshfs [email protected]: ~/net/[email protected]
convmvfs -o srcdir=~/net/[email protected],icharset=KOI8-R,ocharset=UTF-8 ~/net/[email protected]
ls ~/net/[email protected]