标签 文件名中出现特殊字符 下的文章

群晖共享下文件名中出现回车符导致Windows无法读写的处理

前言:

笔者的群晖里面存储的一些文档,突然之间发现不能读取了,尝试打开时Windows系统提示找不到路径。经过再三尝试发现,这些文件可以在Linux下正常读写。在热心网友们的帮助下,经过探索,最终发现不知在哪个阶段、何种原因,文档的名称和扩展名之间被添加了一个回车符(ASCII控制字符,代码:CR,十六进制编码:0x0D,)。而包含这种特殊字符的文件名,在Windows系统下是非法的。最终在网友们的帮助下,解决了这个问题。

简单说一下是如何发现这个特殊字符的。经过热心网友(flaribbit)指导,我使用 ls -l > filename.txt 命令将目录下的文件信息输出到一个txt文本中。然后使用WinHex之类的16进制编辑器直接打开,找到扩展名前的一个字节,查看其数值,然后从ASCII码表中查询即得到结果。

处理过程:

群晖系统的shell太过简单,很多命令不支持,所以我们需要先把其挂载到其他系统中。比如,我挂到了运行Raspbian系统的树莓派下。

Linux系统下挂载CIFS (samba)共享:

以下命令中:

  • //Server 是服务器(即群晖)的主机名或IP
  • Remote_Diretory 是服务器(即群晖)共享的目录(文件夹)名称。
  • Local_Directory 是本地的挂载点,本地的一个空目录(文件夹),需要提前创建好。
  • 后面的 usernamepassword 是用于访问共享的用户名和密码。

挂载命令:

mount -t cifs //Server/Remote_Diretory Local_Directory -o username=xxx,password=xxx

所有操作完成后记得卸载,卸载命令:

umount <Local_Directory>

替换文件名中的回车符:

知道了原因,我们处理的方法有很多,可以写shell脚本,可以用Python写个小程序。此处笔者使用了Linux下的一个软件,名叫 rename。这个软件包群晖上没有,所以我将目录挂载到了Raspbian。

如果系统提示找不到rename,使用以下命令获取:

sudo apt install rename

先使用 cd ./Local_Directory/XXX/ 来到文件的目录,使用以下命令轻松将该目录下所有文件的名称中的回车符去掉:

rename -v  's/\r//g' *

这样就完成了,如果没有其他问题,此时在Windows系统下已经可以正常读写这些文件了。

考虑Linux系统下的兼容性,如果您想要将文件名称中存在的空格换成 _ ,可以使用以下命令:

rename -v  's/ /_/g' *

记得卸载文件系统:

umount <Local_Directory>

以上命令可能看起来有点懵,如果没有学过正则表达式的话。此处稍作解释:

  • -v 是 --verbose,用于在终端中打印成功处理的文件名称,让我们看到处理了哪些文件。

  • 's/ /_/g' 正则表示将空格替换成 _ ,可以看到三个斜杠 / 中有两个位置,前面填入的是要匹配的内容,后面填入要改为的内容。如果后面什么都不填(不是空格!),就是将前面要匹配的内容删掉。

  • 像是要匹配回车符这样的控制字符,或是特殊字符,我们需要使用转义字符来处理,即在前面添加反斜杠。如回车符是 \r

如果我们需要将所有的txt文件的后缀名删除,可以使用以下命令:

rename -v  's/\.txt$//' *.txt
  • 正则中 . 前的 \ 是转义字符。

后记:

经过热心网友们的讨论,我们解决了问题。大佬(Sparkle)提供了使用Python实现的代码,笔者没有测试。

import os
for i in os.listdir('.'):
  os.rename(i,i.replace('\r',"))

总结:

遇到问题,我们首先要明白这是个什么问题,如何用简练的文字把问题的现象描述出来。然后在各大搜索引擎中搜索。搜索无果我们回头继续思考,这可能是什么原因?可以借助调试、日志、转储等判断导致问题的原因。最后分析一下,解决问题大致是个什么流程,可以分成哪些步骤,需要学习哪些新的知识,然后一步一步的学习、解决。