태그 보관물: smb

smb

Windows에서 파일 이름 인코딩 결정 및 변경 설정으로 명령 프롬프트에서 ‘dir’을 실행하면 대체 문자가

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출력

업데이트 된 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테스트 후 제거하십시오 . 너무 길었던 경로에 문제가 있었지만 다른 게시물의 주제입니다.


답변