Windows 서버에 이름에 특정 악센트 문자가있는 파일이 있습니다. Windows 탐색기에서 파일이 정상적으로 표시되지만 기본 설정으로 명령 프롬프트에서 ‘dir’을 실행하면 대체 문자가 표시됩니다.
예를 들어, 문자 ö가 o"목록 과 같이 표시됩니다 . 인코딩 / 코드 페이지가 충돌하여 SMB를 통해 다른 플랫폼에서 이러한 파일에 액세스 할 때 문제가 발생합니다. 모든 파일에 문제가있는 것은 아니며 문제 파일의 출처를 모릅니다.
예:
E:\folder\files>dir
 Volume in drive E is data
 Volume Serial Number is 5841-C30E
 Directory of E:\folder\files
07/05/2016  07:46 PM    <DIR>          .
07/05/2016  07:46 PM    <DIR>          ..
12/01/2015  11:12 AM            14,105 file with o" character.xlsx
01/22/2015  05:30 PM            11,598 file with correct ö character.xlsx
               2 File(s)         25,703 bytes
               2 Dir(s)  2,727,491,600,384 bytes free
파일 및 디렉토리 이름을 변경했지만 아이디어를 얻을 수 있습니다.
어떻게 이런 식으로 이름을 얻었는지 알 수 있습니까? 다른 플랫폼이나 도구를 사용하여 복사하거나 만들었습니까?
모든 문제 파일을 배치하고 이름을 바꾸려면 어떻게해야합니까? GUI 이름 바꾸기 유틸리티 몇 가지를 살펴 봤지만 문제가 표시되지 않고 Windows 탐색기에 표시된 이름으로 만 작동합니다.
드라이브의 파일 시스템이 ReFS인데, 이와 관련이있을 수 있습니까?
편집 : PowerShell 명령 실행
Y:\test>powershell -c Get-ChildItem ^|ForEach-Object {$x=$_.Name; For ($i=0;$i
-lt $x.Length; $i++) {\"{0} {1} {2}\" -f $x,$x[$i],[int]$x[$i]}}
file with o¨ character.xlsx o 111
file with o¨ character.xlsx ¨ 776
관련 부분 만 보이도록 정리했습니다.
실제로 combining diaeresis세로 따옴표가 아닌 것처럼 보입니다 . 내가 이해하는 것처럼 유니 코드 정규화에 대해 이야기 할 때와 마찬가지로.
답변
다음 간단한 Powershell 스크립트를 사용하여 문제를 재현 할 수 있습니다
$RatedName = "šöü"                            # set sample string
$FormDName = $RatedName.Normalize("FormD")    # its Canonical Decomposition
$FormCName = $FormDName.Normalize("FormC")    #     followed by Canonical Composition
                                              # list each string character by character
($RatedName,$FormDName,$FormCName) | ForEach-Object {
    $charArr = [char[]]$_
    "$_"      # display string in new line for better readability
              # display each character together with its Unicode codepoint
    For( $i=0; $i -lt $charArr.Count; $i++ ) {
        $charInt = [int]$charArr[$i]
        # next "Try-Catch-Finally" code snippet adopted from my "Alt KeyCode Finder"
        #                                       http://superuser.com/a/1047961/376602
        Try {
            # Get-CharInfo module downloadable from http://poshcode.org/5234
            #        to add it into the current session: use Import-Module cmdlet
            $charInt | Get-CharInfo |% {
                $ChUCode = $_.CodePoint
                $ChCtgry = $_.Category
                $ChDescr = $_.Description
            }
        }
        Catch {
            $ChUCode = "U+{0:x4}" -f $charInt
            if ( $charInt -le 0x1F -or ($charInt -ge 0x7F -and $charInt -le 0x9F))
                 { $ChCtgry = "Control" } else { $ChCtgry = "" }
            $ChDescr = ""
        }
        Finally { $ChOut = $charArr[$i] }
        "{0} {1,-2} {2} {3,5} {4}" -f $i, $charArr[$i], $ChUCode, $charInt, $ChDescr
    }
}
# create sample files
$RatedName | Out-File "D:\test\1097217Rated$RatedName.txt" -Encoding utf8
$FormDName | Out-File "D:\test\1097217FormD$FormDName.txt" -Encoding utf8
$FormCName | Out-File "D:\test\1097217FormC$FormCName.txt" -Encoding utf8
""                                 # very artless draft of possible solution
Get-ChildItem "D:\test\1097217*" | ForEach-Object {
    $y = $_.Name.Normalize("FormC")
    if ( $y.Length -ne $_.Name.Length ) {
        Rename-Item -NewName $y -LiteralPath $_ -WhatIf
    } else {
        "       : file name is already normalized $_"
    }
}
위의 스크립트는 다음과 같이 업데이트 됩니다. 1st 는 구성 / 분해 된 유니 코드 문자, 즉 해당 유니 코드 이름에 대한 추가 정보를 표시합니다 ( Get-CharInfo 모듈 참조 ). 두 번째 로 가능한 솔루션의 초안 이 포함되어 있습니다.
출력 에서 cmd프롬프트 :
==> powershell -c D:\PShell\SU\1097217.ps1
šöü
0 š  U+0161   353 Latin Small Letter S With Caron
1 ö  U+00F6   246 Latin Small Letter O With Diaeresis
2 ü  U+00FC   252 Latin Small Letter U With Diaeresis
šöü
0 s  U+0073   115 Latin Small Letter S
1 ̌  U+030C   780 Combining Caron
2 o  U+006F   111 Latin Small Letter O
3 ̈  U+0308   776 Combining Diaeresis
4 u  U+0075   117 Latin Small Letter U
5 ̈  U+0308   776 Combining Diaeresis
šöü
0 š  U+0161   353 Latin Small Letter S With Caron
1 ö  U+00F6   246 Latin Small Letter O With Diaeresis
2 ü  U+00FC   252 Latin Small Letter U With Diaeresis
       : file name is already normalized D:\test\1097217FormCšöü.txt
What if: Performing the operation "Rename File" on target "Item: D:\test\1097217
FormDšöü.txt Destination: D:\test\1097217FormDšöü.txt".
       : file name is already normalized D:\test\1097217Ratedšöü.txt
==> dir /b D:\test\1097217*
1097217FormCšöü.txt
1097217FormDšöü.txt
1097217Ratedšöü.txt
실제로 위의 dir출력 은 창과 같 1097217FormDsˇo¨u¨.txt으며 cmd유니 코드 인식 브라우저 는 위에 나열된 문자열 을 작성 하지만 유니 코드 분석기 는 최신 이미지뿐만 아니라 문자를 실제로 표시합니다.
그러나 다음 예제는 전체 너비에서 문제를 보여줍니다. for루프가 악센트를 결합 하여 일반적인 악센트로 변경 합니다.
==> for /F "delims=" %G in ('dir /b /S D:\test\1097217*') do @echo %~nxG & dir /B %~fG
1097217FormCšöü.txt
1097217FormCšöü.txt
1097217FormDsˇo¨u¨.txt
File Not Found
1097217Ratedšöü.txt
1097217Ratedšöü.txt
==>
가능한 해결책에 대한 매우 예술적인 초안 이 있습니다 (위 출력 참조).
""                                 # very artless draft of possible solution
Get-ChildItem "D:\test\1097217*" | ForEach-Object {
    $y = $_.Name.Normalize("FormC")
    if ( $y.Length -ne $_.Name.Length ) {
        Rename-Item -NewName $y -LiteralPath $_ -WhatIf
    } else {
        "       : file name is already normalized $_"
    }
}
( ToDo : Rename-Item필요한 경우에만 호출 ) :
Get-ChildItem "D:\test\1097217*" | ForEach-Object {
    $y = $_.Name.Normalize("FormC")
    if ($true) {                                         ### ToDo
        Rename-Item -NewName $y -LiteralPath $_ -WhatIf
    }
}
그리고 그 출력 (다시, 여기에 구성된 문자열 로 렌더링 되며 아래 이미지는 cmd바이어스되지 않은 창 모양을 보여줍니다 ) :
What if: Performing the operation "Rename File" on target "Item: D:\test\1097217
FormCšöü.txt Destination: D:\test\1097217FormCšöü.txt".
What if: Performing the operation "Rename File" on target "Item: D:\test\1097217
FormDšöü.txt Destination: D:\test\1097217FormDšöü.txt".
What if: Performing the operation "Rename File" on target "Item: D:\test\1097217
Ratedšöü.txt Destination: D:\test\1097217Ratedšöü.txt".
업데이트 된 cmd출력
답변
지역 제어판 의이 탭에서 문제가 발생합니다 .
이것은 화면 글꼴뿐만 아니라 파일 시스템 (기본적으로 설명하는 방식)에도 영향을줍니다.
스크린 샷은 내 컴퓨터에서 가져온 것입니다. 로케일을 영어로 변경하면 ľôščťž 파일 이름 과 같은 모든 특수 슬로바키아어 국가 문자 가 쓰레기가되고 일부는 해결 방법없이 파일을 열지 못하게합니다 (코드 페이지가 되돌릴 때까지). . 그러나이 문제는 áíé여러 언어에서 볼 수있는 보다 일반적인 자국 문자로는 나타나지 않습니다 .
이는 다른 로케일로 작성된 백업을 열려고하는 등 일부 오프라인 매체에도 영향을줍니다.
가장 쉬운 해결책은 리소스에 액세스하는 모든 컴퓨터에서 동일한 로캘을 유지하는 것입니다.
해결 방법은 다른 로케일을 가진 시스템을 판별하고 해당 시스템과 모든 파일 이름에서 모든 국가 문자 (예 : č-> c, ž-> z) 의 대량 교체를 수행하는 시스템을 판별하는 것입니다 . Total Commander (파일 관리자)는 전체 디렉토리 트리에서 이러한 각 쌍을 한 번에 교체 할 수 있습니다. 그런 다음 해당 머신을 영어로 되돌 리거나 (자체 백업을 읽지 못할 수도 있음) 사용자가 파일 이름에 자국 문자를 사용하지 않도록 요청하여 그대로 유지할 수 있습니다.
(하지만 그 전에 한 가지 시도를 할 수 있습니다. chcp다른 로케일로 시스템에서 실행 하고, 사용중인 코드 페이지 (예 : 852)를 학습 한 다음로 다른 시스템에서 시도해보십시오 chcp 852. 문제가 만족스럽게 해결되는지 여부는 확실하지 않습니다.)
답변
JosefZ의 스크립트를 기반으로 다음은 재귀 적으로 작동하는 수정 된 버전입니다.
Get-ChildItem "X:\" -Recurse | ForEach-Object {
    $y = $_.Name.Normalize("FormC")
    $file = $_.Fullname
    if ( $y.Length -ne $_.Name.Length ) {
        Rename-Item -LiteralPath "$file" -NewName "$y" -WhatIf
        Write-Host "renamed file $file"
    }
}
-WhatIf테스트 후 제거하십시오 . 너무 길었던 경로에 문제가 있었지만 다른 게시물의 주제입니다.



