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