如何找到所有与 Windows 不兼容的路径?

l0b*_*0b0 6 shell bash windows filenames ext2fsd

在大多数 Linux 文件系统上,NUL ( \0) 是路径中唯一的无效字符(并/保留为路径分隔符)。Windows 有一套复杂的有效路径规则。与其自动修复路径(危险,可能导致文件覆盖另一个文件),我如何才能找到与 Windows 不兼容的目录中的所有路径?

最初的问题是我的Google Drive文件夹位于使用ext2fs挂载的驱动器上,但官方 Gdrive 客户端告诉我无法同步数千个文件。我找不到任何错误消息,当我要求它向我展示文件时,它只会无限期地挂起。重新启动客户端或操作系统并没有帮助,但我有一种预感,修复任何非 Windows 兼容的路径都会解除 Gdrive。好像成功了……

l0b*_*0b0 5

具有保留名称/字符的路径:

LC_ALL=C find . -name '*[[:cntrl:]<>:"\\|?*]*' \
             -o -iname 'CON' \
             -o -iname 'PRN' \
             -o -iname 'AUX' \
             -o -iname 'NUL' \
             -o -iname 'COM[1-9]' \
             -o -iname 'LPT[1-9]' \
             -o -name '* ' \
             -o -name '?*.'
Run Code Online (Sandbox Code Playgroud)

测试:

$ cd -- "$(mktemp --directory)"
$ touch foo \\ LPT9 'space ' 'dot.'
$ LC_ALL=C find . -name '*[[:cntrl:]<>:"\\|?*]*' -o -iname 'CON' -o -iname 'PRN' -o -iname 'AUX' -o -iname 'NUL' -o -iname 'COM[1-9]' -o -iname 'LPT[1-9]' -o -name '* ' -o -name '?*.'
./dot.
./space 
./LPT9
./\
Run Code Online (Sandbox Code Playgroud)

忽略大小写时相同的路径(不适用于包含换行符的路径):

find . | sort | LC_ALL=C tr '[:upper:]' '[:lower:]' | uniq -c | grep -v '^      1 ' | cut -c '9-'
Run Code Online (Sandbox Code Playgroud)

测试:

$ cd -- "$(mktemp --directory)"
$ touch foo bar BAR
$ find . | sort | LC_ALL=C tr '[:upper:]' '[:lower:]' | LC_ALL=C uniq -c | grep -v '^      1 ' | cut -c '9-'
./bar
Run Code Online (Sandbox Code Playgroud)

路径长度超过MAX_PATH(260 个字符):

find "$PWD" | while IFS= read -r path
do
    if [ "${#path}" -gt 260 ]
    then
        printf '%s\n' "$path"
    fi
done
Run Code Online (Sandbox Code Playgroud)

测试:

$ cd -- "$(mktemp --directory)"
$ touch foo 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
$ find "$PWD" | while IFS= read -r path
> do
>     if [ "${#path}" -gt 260 ]
>     then
>         printf '%s\n' "$path"
>     fi
> done
/tmp/tmp.HEANyAI8Hy/123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
Run Code Online (Sandbox Code Playgroud)