在备份我的目录时,名称包含 ę、ą、ż、ź 等波兰语字符的目录被“重复”。
当我这样做时,ls -al
我得到如下回复:
drwxrwxr-x+ 310 root users 313 Oct 9 16:18 .
drwxrwxr-x+ 13 root users 14 Dec 1 2019 ..
drwxrwxr-x+ 2 root users 83 May 16 2021 '050805 - PKP Międzyzdroje'
drwxrwxr-x+ 2 root users 83 Nov 8 2019 '050805 - PKP Międzyzdroje'
但是,当我尝试对目录执行某些操作(例如ls
或mv
)时,zsh 会以不同的方式自动完成目录:
带有正确编码的“ę”的选项:
ls 050805\ -\ PKP\ Międzyzdroje/
带有 4 符号 unicode 字符“<0328>”的选项:
ls 050805\ -\ PKP\ Mie<0328>dzyzdroje/
问题:如何找到包含这些 4 符号 unicode 字符的所有目录,以便将其重命名为某个 ASCII 名称,然后对它们进行重复数据删除?
FWIW,我的主机在 Debian 上,但我可能是通过 Samba 使用 macOS 客户端导致了这个问题。
答案1
您有一些文件的ę
预组合形式(U+0119 带有 OGONEK 的拉丁文小写字母 E)和一个其分解形式的文件,e
后跟 U+0328 COMBINING OGONEK。
众所周知,macOS 会将文件名中的文本转换为分解形式,从而导致各种问题。
要查找包含 U+0328 字符的文件名,请使用zsh
:
ls -ld -- **/*$'\u328'*(D)
或者找到那些带有任何组合标记的:
set -o rematchpcre
ls -ld -- **/*(De['[[ $REPLY:t =~ "\pM" ]]'])
或者定义一个辅助函数:
hasMarks() {
set -o localoptions -o rematchpcre
[[ $REPLY:t =~ '\pM' ]]
}
ls -ld -- **/*(D+hasMarks)
要从分解转换为预组合,在任何类似 POSIX 的 shell 中并假设文件名不以换行符结尾:
precomposed=$(printf '%s\n' "$decomposed" | uconv -x nfc)
或者zsh
不必做出这样的假设:
printf -rN - $decomposed | uconv -x nfc | IFS= read -rd '' precomposed
(在 Debian 上的包uconv
中icu-devtools
)。
因此,要重命名它们,请在zsh
:
set -o rematchpcre -o pipefail
for file (**/*(NDode['[[ $REPLY:t =~ "\pM" ]]']))
print -rN - $file:t | uconv -x nfc | IFS= read -rd '' new &&
mv -Tvi -- $file $file:h/$new