BSD - 以递归方式从目录中的所有文件中删除非 ASCII 字符

BSD - 以递归方式从目录中的所有文件中删除非 ASCII 字符

我正在尝试将一堆(300GB+)文件从 FAT32 驱动器迁移到我的 freeNas ZFS 文件系统,但是我向它发出的每个命令(tar、pax、mv、cp)在遇到非 ASCII 文件名时都会抛出“无效参数” - 它通常是在 Windows 下创建的,它会读取类似于“foo?s bar.mp3...”的内容,其中?可能是撇号或类似符号。

有人能帮忙用几行代码递归遍历目录树并重命名文件以删除有问题的字符吗?

非常感激。

答案1

尝试将 iocharset 选项设置为其使用的编码来挂载文件系统。

man mount“Fat 的安装选项”部分下:

   iocharset=value
          Character set to use for converting between 8 bit characters and
          16 bit Unicode characters. The default is iso8859-1.  Long file‐
          names are stored on disk in Unicode format.

另请参阅“vfat 的挂载选项”部分:

   uni_xlate
          Translate  unhandled  Unicode  characters  to  special   escaped
          sequences.   This lets you backup and restore filenames that are
          created with any Unicode characters. Without this option, a  '?'
          is used when no translation is possible. The escape character is
          ':' because it is otherwise illegal on the vfat filesystem.  The
          escape  sequence  that gets used, where u is the unicode charac‐
          ter, is: ':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12).

   utf8   UTF8  is  the  filesystem safe 8-bit encoding of Unicode that is
          used by the console. It can be be  enabled  for  the  filesystem
          with this option or disabled with utf8=0, utf8=no or utf8=false.
          If `uni_xlate' gets set, UTF8 gets disabled.

编辑:

对不起,那是 Linux,这是 BSD 的(来自man mount_msdosfs

 -L locale
     Specify locale name used for file name conversions for DOS and
     Win'95 names.  By default ISO 8859-1 assumed as local character
     set.

 -D DOS_codepage
     Specify the MS-DOS code page (aka IBM/OEM code page) name used
     for file name conversions for DOS names.

答案2

重命名可以做到这一点..

尝试类似

find dir -depth -exec rename -n 's/[^[:ascii:]]/_/g' {} \; | cat -v

您可能需要 cat -v 来正确显示任何奇怪的字符,而不会让您的终端陷入混乱。

如果打印出可接受的替换,则将 -n 更改为 -v。

也就是说,听起来你的文件系统上的字符集是错误的(mount -o utf8?),因为这种事情应该确实有效......

答案3

这是递归应用的一种正确方法:

find . -depth -execdir rename 'y/[\:\;\>\<\@\$\#\&\(\)\?\\\%\ ]/_/' {} \;

将所有符号改为下划线。请注意,所有空格均视为空格。

为什么它有效? 做一下这个测试:

mkdir test

cd test

mkdir -p a$/b$/c$/d$ f%/g%/h%/i% j%/k%/l%/m%

find . -depth -execdir rename 'y/[\:\;\>\<\@\$\#\&\(\)\?\\\%\ ]/_/' {} \;

ls -R

(如您所见,所有文件都已更改)

答案4

用下划线替换:

find . | perl -ane '{ if(m/[[:^ascii:]]/) { print } }' | rename -n 's/[^[:ascii:]]/_/g'

相关内容