批量删除文件名中不可见的字符

批量删除文件名中不可见的字符

我的外部驱动器上有数百个文件,这些文件可能被复制了很多,并且也可能在某个时候恢复。文件名似乎在其生命周期中获得了一些奇怪的字符,我需要修复它们。

问题是我可以用 列出它们ls,但我不能通过引用它们的名字来对它们做任何事情。

ls -l呈现此结果:

-rwx------  1 krzysztof  staff  322451 Jun 27  2009 file015.jpg
-rwx------  1 krzysztof  staff  331337 Jun 27  2009 file016.jpg
-rwx------  1 krzysztof  staff  303078 Jun 27  2009 file017.jpg
-rwx------  1 krzysztof  staff  312346 Jun 27  2009 file018.jpg

文件本身没有损坏,如果我手动更改名称,问题就会消失。我还可以创建一个名称看似完全相同的文件(并且两者将同时显示ls)。这让我相信隐形字符中存在一些可疑的情况,我通过运行确认了这一点find . -name '*[! -~]*'- 它返回了所有有问题的文件的列表。

我通常不会关心这些名称,但某些应用程序和工具显然也对它们有问题,并且直接看不到它们或忽略它们。

一个例子是detox我第一次尝试用来修复名称的工具 - 它只是假装它们不存在。

exiftool抛出No such file or directory。类似地,通过管道传输ls -1到循环,或将文件名保存到文件中,然后通过管道传输它们总是会产生各种形式No such file or directory。就像管道或保存时不保留不可见字符一样?

$ while read p; do
  mv "$p" "$p"
done <`find . -name '*.jpg'`
zsh: no such file or directory: ./file015.jpg

有没有办法批量清理文件名?

编辑1:

根据 @terdon 的要求,我尝试了ls -v,但ls -B没有任何结果。

然而,这ls | head -n1 | od -c更有趣,也让我有了自己的发现。在这里,我欠你一个道歉,因为在我最初的问题中,我改变了名字,因为我认为这并不重要,但事实确实如此。

这样,以下是实际输出,其中文件 014 已手动修复,其余部分已损坏:

❯ ls -1
Zdjęcie014.jpg
Zdjęcie015.jpg
Zdjęcie016.jpg
Zdjęcie017.jpg
Zdjęcie018.jpg

这是ls | head -n2 | od -c- 我曾经n2显示的不仅仅是第一个文件名。

❯ ls | head -n2 | od -c
0000000    Z   d   j   e    ̨  **   c   i   e   0   1   4   .   j   p   g
0000020   \n   Z   d   j   e    ̨  **   c   i   e   0   1   5   .   j   p
0000040    g  \n
0000042

在此输入图像描述

正如您所看到的,两个文件中都有一个ę字符,并且在ls | head -n2 | od -c.但!当我返回手动编辑和重命名文件时,在 014(固定文件)中,当我将光标放在后面ę并按退格键时,整个字符消失。对于其他文件而言,情况并非如此 - 按退格键ę会将其更改为e,并且只有第二个退格键才会将其删除。

谢谢@terdon - 现在我们知道问题出在哪里了。如何批量修复此问题?

编辑2:

014 已修复,015 已损坏:

❯ ls | head -n2 | LC_ALL=C sed -n l
Zdje\314\250cie014.jpg$
Zdje\314\250cie015.jpg$

编辑3:

正如评论中所建议的,我尝试应用解决方案如何在 macOS 上重命名带有重音符号的文件名?但再次遇到No such file or directory

❯ rename $'s/\u119/e/g' ./*
Can't rename './Zdjęcie015.jpg' to './Zdjecie015.jpg': No such file or directory

rename $'s/\u0328//g' ./*在 bash 和 zsh 中不执行任何操作

编辑4:

❯ PERL_UNICODE=ASD find . -depth -execdir rename -n 's/\pM//g' {} +
'Zdjęcie015.jpg' would be renamed to 'Zdjecie015.jpg'

❯ PERL_UNICODE=ASD find . -depth -execdir rename 's/\pM//g' {} +
Can't rename 'Zdjęcie015.jpg' to 'Zdjecie015.jpg': No such file or directory

答案1

我不确定这是否真的是一个答案,因为我无法使其在 macOS 上运行,但这确实是解决我的问题的解决方法。

由于外部驱动器是 NAS,因此我通过 ssh 进入它并直接解决了问题。不幸的是,我无法使用像这样的奇特工具rename,所以我不得不使用find,mvsed- 并且它工作得恰到好处!

这是我使用的命令:

find ./ -maxdepth 1 -name "*.JPG" -exec sh -c 'mv "$1" "$(echo "$1" | sed s/Zdj.*cie/zdjecie/)"' _ {} \;

PS感谢评论区大侠一路以来的帮助!

相关内容