名前に特定のアクセント付き文字が含まれているファイルが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
であり、垂直引用符ではないように見えます。私が理解しているように、ユニコードの正規化について話すときはそうあるべきです。
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
テスト後。パスが長すぎるという問題がありましたが、それは別の投稿のトピックです。
次の簡単な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 $_"
}
}
上記のスクリプトは次のようにupdatedです:1stはcomposed /に関する詳細情報を示しています分解されたUnicode文字、つまりそれらのUnicode名( Get-CharInfoモジュール を参照)。 2番目埋め込み可能な解決策の非常に芸術的なドラフト。
出力from 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
出力lookscmd
ウィンドウと私のUnicode対応ブラウザの1097217FormDsˇo¨u¨.txt
のように 文字列を構成 リストされているように上記ですが nicodeアナライザー 文字と最新の画像が表示されます:
ただし、次の例では、問題を全幅で示しています。for
ループがcombiningアクセントをnormalアクセントに変更します。
==> 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(ファイルマネージャー)は、ディレクトリツリー全体でこのような各ペアの置換を一度に実行できます。次に、そのマシンを英語に戻すか(独自のバックアップを読み取れない場合があることに注意してください)、ファイル名に国別文字を使用しないようにユーザーに要求して、そのままにしておくことができます。
(それでも前に、1つのことを試すことができます。その異なるロケールのマシンでchcp
を実行し、使用されているコードページ(たとえば852)を学習してから、chcp 852
を使用して他のマシンで試すことができます。これで問題が十分に解決するかどうかはわかりません。)