![通过 ssh 使用不同编码的文件名](https://linux22.com/image/19115/%E9%80%9A%E8%BF%87%20ssh%20%E4%BD%BF%E7%94%A8%E4%B8%8D%E5%90%8C%E7%BC%96%E7%A0%81%E7%9A%84%E6%96%87%E4%BB%B6%E5%90%8D.png)
我正在通过 ssh 连接到远程系统,其中使用了不同的文件名编码(以及用户的区域设置)。这会导致一些问题。
通过匹配区域设置解决的问题
在讨论文件名问题之前,我想说一下此类 ssh 会话的一些编码问题通过设置远程区域设置使其与本地区域设置匹配来解决,即
- 编辑命令行的问题(我按了三次退格键,但由于在我的主机上编码是 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
,因此我能够选择并粘贴它($''
在巴什):
[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),它们采用不同的编码?
如果它们是可读的、可选择的和可粘贴的(并且也可以由我从键盘输入,然后可以通过 Tab 完成),那就太好了巴什;当然,为了方便我打字,它们必须可读)。
我工作于乌尔克斯VT在X.org在Linux在本地主机上,它是巴什在Linux在远端。
答案1
在支持 UTF-8 的终端模拟器中,您可以使用luit
命令在不同的语言环境中运行子 shell(或其他程序)。指示字符集的区域设置是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)
如果您有不同编码的整个文件树,我建议(如果可能)通过安装它转换文件系统。
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]
答案2
也许,人们可能会考虑使用一些复杂的终端模拟器,例如屏幕(在任一端)将翻译字符,(或使用一些翻译扩展SSH...),或者可以设置一个转换文件系统文件系统视图远程(文件名重新编码为本地编码),但有一个简单的解决方案:
只需在本地主机上创建一个专门用于与该远程主机一起工作的“环境”,并在该环境中工作(运行ssh等),即在远程文件名是CP1251的情况下,启动一个新的航站楼X这适用于该编码:
$ LC_CTYPE=ru_RU.CP1251 xvt &
并从中开展工作。 (如果你比 X 更喜欢 Linux 控制台,也许你可以相应地设置一个虚拟 Linux 控制台,但关于设置 Linux 控制台的知识已经从我的脑海中消失了......)