Windowsと互換性のないすべてのパスを見つける方法は?

Windowsと互換性のないすべてのパスを見つける方法は?

ほとんどのLinuxファイルシステムでは、NUL(\0)はパスで唯一無効な文字です(パス区切り/文字で予約されています)。Windowsには、有効なパスの複雑なルールセットがあります。。パスを自動的に回復する代わりに(危険、あるファイルが別のファイルを上書きする可能性があります)Windowsと互換性のないディレクトリですべてのパスを見つける方法は?

元の質問は私のものでした。Googleドライブフォルダは、次を使用してインストールされたドライブにあります。ext2fsしかし、公式Gdriveクライアントは何千ものファイルを同期できないと言います。エラーメッセージが見つからず、ファイルを表示するように要求すると無期限に中断されます。クライアントまたはOSを再起動しても役に立ちませんでしたが、予感しました。Windowsと互換性のないパスを修正してください。Gdriveはキャンセルされます。効果があったようです...

答え1

予約された名前/文字のパス:

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 '?*.'

テスト:

$ 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
./\

大文字と小文字を無視するときの同じパス(改行文字を含むパスでは機能しません。):

find . | sort | LC_ALL=C tr '[:upper:]' '[:lower:]' | uniq -c | grep -v '^      1 ' | cut -c '9-'

テスト:

$ 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

パスの長さが以下を超えていますMAX_PATH(260文字):

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

テスト:

$ 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

答え2

Perlソリューションの場合は、このモジュールを使用できますWin32::Filenames

http://search.cpan.org/~bch/Win32-Filenames-0.01/lib/Win32/Filenames.pm

このモジュールを使用する簡単なプログラム:

#!/usr/bin/env perl

use strict;
use warnings;

use Win32::Filenames qw(validate sanitize);

while ( my $filename = shift ) {
    printf( "checking filename %s\t", $filename );

    if ( validate($filename) ) {
        print("ok.\n");
    }
    else {
        printf( "failed, try this instead: %s\n", sanitize($filename) );
    }
}

1つ以上のファイル名を使用してコマンドラインから呼び出すことができます。

$ ./check.pl '<a>' 'hi?' '"right"' 'pipe|me'
checking filename <a>   failed, try this instead: -a-
checking filename hi?   failed, try this instead: hi-
checking filename "right"       failed, try this instead: -right-
checking filename pipe|me       failed, try this instead: pipe-me

フルファイル階層の場合:

$ find . -exec basename {} \; | xargs ./check.pl

関連情報