حفظ نتائج "شجرة /f /a" في ملف نصي مع دعم يونيكود
-
02-07-2019 - |
سؤال
أحاول استخدام أمر الشجرة في سطر أوامر Windows لإنشاء ملف نصي يسرد محتويات الدليل، ولكن عندما أقوم بتوجيه الإخراج، تصبح أحرف Unicode محشوة.
إليك الأمر الذي أستخدمه:
tree /f /a > output.txt
النتائج في نافذة وحدة التحكم جيدة:
\---Erika szobája cover.jpg Erika szobája.m3u Kátai Tamás - 01 Télvíz.ogg Kátai Tamás - 02 Zölderdõ.ogg Kátai Tamás - 03 Renoir kertje.ogg Kátai Tamás - 04 Esõben szaladtál.ogg Kátai Tamás - 05 Ázik az út.ogg Kátai Tamás - 06 Sûrû völgyek takaród.ogg Kátai Tamás - 07 Õszhozó.ogg Kátai Tamás - 08 Mécsvilág.ogg Kátai Tamás - 09 Zúzmara.ogg
لكن الملف النصي ليس جيدًا:
\---Erika szob ja cover.jpg Erika szob ja.m3u K tai Tam s - 01 T‚lv¡z.ogg K tai Tam s - 02 Z”lderdä.ogg K tai Tam s - 03 Renoir kertje.ogg K tai Tam s - 04 Esäben szaladt l.ogg K tai Tam s - 05 µzik az £t.ogg K tai Tam s - 06 S–r– v”lgyek takar¢d.ogg K tai Tam s - 07 åszhoz¢.ogg K tai Tam s - 08 M‚csvil g.ogg K tai Tam s - 09 Z£zmara.ogg
كيف يمكنني اصلاح هذا؟من الناحية المثالية، سيكون الملف النصي مطابقًا تمامًا للإخراج الموجود في نافذة وحدة التحكم.
لقد جربت اقتراح Chris Jester-Young (ماذا حدث، هل قمت بحذفه يا كريس؟) لتشغيل سطر الأوامر باستخدام المفتاح /U، بدا الأمر تمامًا كما أحتاجه ولكن لا يبدو أنه يعمل.لقد حاولت فتح الملف في كل من VS2008 والمفكرة وكلاهما يظهر نفس الأحرف غير الصحيحة.
المحلول
هل جرب شخص ما هذا بالفعل:
tree /f /a |clip
هل تريد فتح المفكرة باستخدام ctrl + V وحفظها في المفكرة بصيغة input.txt مع دعم Unicode؟
نصائح أخرى
إذا قمت بالإخراج بتنسيق غير Unicode (وهو ما تفعله على ما يبدو)، فيجب عليك عرض الملف النصي الذي قمت بإنشائه باستخدام نفس التشفير الذي تستخدمه نافذة وحدة التحكم.لهذا السبب يبدو صحيحًا في وحدة التحكم.في بعض برامج تحرير النصوص، يمكنك اختيار ترميز (أو "صفحة رموز") عند فتح ملف.(كيفية الإخراج كـ Unicode لا أعرف.cmd /U لا يفعل ما تقوله الوثائق.)
يعتمد ترميز وحدة التحكم على تثبيت Windows لديك.بالنسبة لي، إنه "أوروبا الغربية (DOS)" (أو فقط "MS-DOS") في Microsoft Word.
استخدم بوويرشيل:
powershell -command "tree /f > tree.txt"
حالة اختبار:
create.ps1
:
mkdir "Erika szobája"
$null | Set-Content "Erika szobája/cover.jpg"
$null | Set-Content "Erika szobája/Erika szobája.m3u"
$null | Set-Content "Erika szobája/Kátai Tamás - 01 Télvíz.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 02 Zölderdõ.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 03 Renoir kertje.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 04 Esõben szaladtál.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 05 Ázik az út.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 06 Sûrû völgyek takaród.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 07 Õszhozó.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 08 Mécsvilág.ogg"
$null | Set-Content "Erika szobája/Kátai Tamás - 09 Zúzmara.ogg"
انتاج:
tree.txt
:
Folder PATH listing
Volume serial number is 00000000 0000:0000
C:.
│ create.ps1
│ tree.txt
│
└───Erika szobája
cover.jpg
Erika szobája.m3u
Kátai Tamás - 01 Télvíz.ogg
Kátai Tamás - 02 Zölderdo.ogg
Kátai Tamás - 03 Renoir kertje.ogg
Kátai Tamás - 04 Esoben szaladtál.ogg
Kátai Tamás - 05 Azik az út.ogg
Kátai Tamás - 06 Sûrû völgyek takaród.ogg
Kátai Tamás - 07 Oszhozó.ogg
Kátai Tamás - 08 Mécsvilág.ogg
Kátai Tamás - 09 Zúzmara.ogg
يحرر:
نسخة محسنة ومحسنة لمستخدمي الطاقة
حالة اختبار:
$null | Set-Content "欲速则不达.txt"
$null | Set-Content "爱不是占有,是欣赏.txt"
$null | Set-Content "您先请是礼貌.txt"
$null | Set-Content "萝卜青菜,各有所爱.txt"
$null | Set-Content "广交友,无深交.txt"
$null | Set-Content "一见钟情.txt"
$null | Set-Content "山雨欲来风满楼.txt"
$null | Set-Content "悪妻は百年の不作。.txt"
$null | Set-Content "残り物には福がある。.txt"
$null | Set-Content "虎穴に入らずんば虎子を得ず。.txt"
$null | Set-Content "夏炉冬扇.txt"
$null | Set-Content "花鳥風月.txt"
$null | Set-Content "起死回生.txt"
$null | Set-Content "自業自得.txt"
$null | Set-Content "아는 길도 물어가라.txt"
$null | Set-Content "빈 수레가 요란하다.txt"
$null | Set-Content "방귀뀐 놈이 성낸다.txt"
$null | Set-Content "뜻이 있는 곳에 길이 있다.txt"
$null | Set-Content "콩 심은데 콩나고, 팥 심은데 팥난다.txt"
منه إجابة, ، كتب @Chris Jester-Young:
في هذه اللحظة
ulib
, ، الWriteString
يتم تنفيذ الطريقة في فئتين ،SCREEN
وSTREAM
.الSCREEN
يستخدم الإصدارWriteConsoleW
مباشرة ، لذلك يتم عرض جميع أحرف Unicode بشكل صحيح.الSTREAM
يحول الإصدار نص Unicode إلى واحد من ثلاثة ترميزات مختلفة (_UseConsoleConversions
codepage وحدة التحكم (GetConsoleCP
),_UseAnsiConversions
⇒ الافتراضي ANSI Codepage ، وإلا
هذا يعني أنه لا يمكننا الاعتماد على الحصول على الأحرف من الدفق.لن تعمل عمليات إعادة توجيه الملفات.علينا أن نعتمد على الكتابة إلى وحدة التحكم للحصول على أحرف Unicode.
الحل البديل، أو الاختراق، هو كتابة الشجرة على وحدة التحكم ثم تفريغ المخزن المؤقت في ملف.
لقد قمت بكتابة البرامج النصية لإضافة قائمة سياق الشجرة عند النقر بزر الماوس الأيمن على الدلائل في Explorer.احفظ الملفات في نفس الدليل ثم قم بتشغيلها Install list menu.bat
كمسؤول للتثبيت.
Install list menu.bat
@echo on
regedit /s "List files.reg"
copy "List.ps1" "%SystemRoot%"
pause
List files.reg
Windows Registry Editor Version 5.00
; Directory.
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Shell\List]
"MUIVerb"="List"
"ExtendedSubCommandsKey"="Directory\\ContextMenus\\List"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\ContextMenus\List\Shell\Files]
"MUIVerb"="Files"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\ContextMenus\List\Shell\Files\Command]
; powershell -executionPolicy bypass "%SystemRoot%\List.ps1" -type 'files' -directory '%1'
@=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,20,00,2d,\
00,65,00,78,00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,00,6c,00,\
69,00,63,00,79,00,20,00,62,00,79,00,70,00,61,00,73,00,73,00,20,00,22,00,25,\
00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,00,5c,00,\
4c,00,69,00,73,00,74,00,2e,00,70,00,73,00,31,00,22,00,20,00,2d,00,74,00,79,\
00,70,00,65,00,20,00,27,00,66,00,69,00,6c,00,65,00,73,00,27,00,20,00,2d,00,\
64,00,69,00,72,00,65,00,63,00,74,00,6f,00,72,00,79,00,20,00,27,00,25,00,31,\
00,27,00,00,00
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\ContextMenus\List\Shell\FilesRecursively]
"MUIVerb"="Files recursively"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\ContextMenus\List\Shell\FilesRecursively\Command]
; powershell -executionPolicy bypass "%SystemRoot%\List.ps1" -type 'filesRecursively' -directory '%1'
@=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,20,00,2d,\
00,65,00,78,00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,00,6c,00,\
69,00,63,00,79,00,20,00,62,00,79,00,70,00,61,00,73,00,73,00,20,00,22,00,25,\
00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,00,5c,00,\
4c,00,69,00,73,00,74,00,2e,00,70,00,73,00,31,00,22,00,20,00,2d,00,74,00,79,\
00,70,00,65,00,20,00,27,00,66,00,69,00,6c,00,65,00,73,00,52,00,65,00,63,00,\
75,00,72,00,73,00,69,00,76,00,65,00,6c,00,79,00,27,00,20,00,2d,00,64,00,69,\
00,72,00,65,00,63,00,74,00,6f,00,72,00,79,00,20,00,27,00,25,00,31,00,27,00,\
00,00
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\ContextMenus\List\Shell\Tree]
"MUIVerb"="Tree"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\ContextMenus\List\Shell\Tree\Command]
; powershell -executionPolicy bypass "%SystemRoot%\List.ps1" -type 'tree' -directory '%1'
@=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,20,00,2d,\
00,65,00,78,00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,00,6c,00,\
69,00,63,00,79,00,20,00,62,00,79,00,70,00,61,00,73,00,73,00,20,00,22,00,25,\
00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,00,5c,00,\
4c,00,69,00,73,00,74,00,2e,00,70,00,73,00,31,00,22,00,20,00,2d,00,74,00,79,\
00,70,00,65,00,20,00,27,00,74,00,72,00,65,00,65,00,27,00,20,00,2d,00,64,00,\
69,00,72,00,65,00,63,00,74,00,6f,00,72,00,79,00,20,00,27,00,25,00,31,00,27,\
00,00,00
; Directory background.
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Background\Shell\List]
"MUIVerb"="List"
"ExtendedSubCommandsKey"="Directory\\Background\\ContextMenus\\List"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Background\ContextMenus\List\Shell\Files]
"MUIVerb"="Files"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Background\ContextMenus\List\Shell\Files\Command]
; powershell -executionPolicy bypass "%SystemRoot%\List.ps1" -type 'files' -directory '%V'
@=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,20,00,2d,\
00,65,00,78,00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,00,6c,00,\
69,00,63,00,79,00,20,00,62,00,79,00,70,00,61,00,73,00,73,00,20,00,22,00,25,\
00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,00,5c,00,\
4c,00,69,00,73,00,74,00,2e,00,70,00,73,00,31,00,22,00,20,00,2d,00,74,00,79,\
00,70,00,65,00,20,00,27,00,66,00,69,00,6c,00,65,00,73,00,27,00,20,00,2d,00,\
64,00,69,00,72,00,65,00,63,00,74,00,6f,00,72,00,79,00,20,00,27,00,25,00,56,\
00,27,00,00,00
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Background\ContextMenus\List\Shell\FilesRecursively]
"MUIVerb"="Files recursively"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Background\ContextMenus\List\Shell\FilesRecursively\Command]
; powershell -executionPolicy bypass "%SystemRoot%\List.ps1" -type 'filesRecursively' -directory '%V'
@=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,20,00,2d,\
00,65,00,78,00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,00,6c,00,\
69,00,63,00,79,00,20,00,62,00,79,00,70,00,61,00,73,00,73,00,20,00,22,00,25,\
00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,00,5c,00,\
4c,00,69,00,73,00,74,00,2e,00,70,00,73,00,31,00,22,00,20,00,2d,00,74,00,79,\
00,70,00,65,00,20,00,27,00,66,00,69,00,6c,00,65,00,73,00,52,00,65,00,63,00,\
75,00,72,00,73,00,69,00,76,00,65,00,6c,00,79,00,27,00,20,00,2d,00,64,00,69,\
00,72,00,65,00,63,00,74,00,6f,00,72,00,79,00,20,00,27,00,25,00,56,00,27,00,\
00,00
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Background\ContextMenus\List\Shell\Tree]
"MUIVerb"="Tree"
[HKEY_LOCAL_MACHINE\Software\Classes\Directory\Background\ContextMenus\List\Shell\Tree\Command]
; powershell -executionPolicy bypass "%SystemRoot%\List.ps1" -type 'tree' -directory '%V'
@=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,20,00,2d,\
00,65,00,78,00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,00,6c,00,\
69,00,63,00,79,00,20,00,62,00,79,00,70,00,61,00,73,00,73,00,20,00,22,00,25,\
00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,00,5c,00,\
4c,00,69,00,73,00,74,00,2e,00,70,00,73,00,31,00,22,00,20,00,2d,00,74,00,79,\
00,70,00,65,00,20,00,27,00,74,00,72,00,65,00,65,00,27,00,20,00,2d,00,64,00,\
69,00,72,00,65,00,63,00,74,00,6f,00,72,00,79,00,20,00,27,00,25,00,56,00,27,\
00,00,00
List.ps1
function sortNaturally {
[Regex]::replace($_, '\d+', {
$args[0].value.padLeft(20)
})
}
function writeList {
param(
[parameter(mandatory = $true)]
[string] $text = $null
)
$filePath = "$env:temp\List.txt"
$text > "$filePath"
notepad "$filePath" | out-null
del "$filePath"
}
function listFiles {
param(
[switch] $recurse = $false
)
get-childItem -name -recurse:$recurse -force | sort-object $function:sortNaturally | out-string
}
function listTree {
tree /f
}
function getBufferText {
$rawUi = $host.ui.rawUi
$width = [Math]::max([Math]::max($rawUi.bufferSize.width, $rawUi.windowSize.width) - 1, 0)
$height = [Math]::max($rawUi.cursorPosition.y - 1, 0)
$lines = new-object System.Text.StringBuilder
$characters = new-object System.Text.StringBuilder
for ($h = 0; $h -lt $height; $h += 1) {
$rectangle = new-object System.Management.Automation.Host.Rectangle 0, $h, $width, $h
$buffer = $rawUi.getBufferContents($rectangle)
for ($w = 0; $w -lt $width; $w += 1) {
$cell = $buffer[0, $w]
$character = $cell.character
$characters.append($character) | out-null
}
$lines.appendLine($characters.toString()) | out-null
$characters.length = 0
}
$lines.toString() -replace '[ \0]*\r?\n', "`r`n"
}
function main {
param(
[parameter(mandatory = $true)]
[string] $type = $null,
[parameter(mandatory = $true)]
[string] $directory = $null
)
$outputEncoding = [Text.UTF8Encoding]::UTF8
[Console]::outputEncoding = [Text.UTF8Encoding]::UTF8
$PSDefaultParameterValues['out-file:encoding'] = 'utf8'
set-location -literalPath "$directory"
$typeFunction = @{
'files' = { writeList -text $(listFiles) };
'filesRecursively' = { writeList -text $(listFiles -recurse) };
'tree' = {
listTree
writeList -text $(getBufferText)
}
}
&($typeFunction.get_item($type))
}
main @args
قررت أنني يجب أن ألقي نظرة tree.com
واكتشف سبب عدم احترام إعداد Unicode لوحدة التحكم.اتضح أنه (مثل العديد من الأدوات المساعدة لملفات سطر الأوامر)، يستخدم مكتبة تسمى ulib.dll
للقيام بجميع عمليات الطباعة (على وجه التحديد، TREE::DisplayName
المكالمات WriteString
في ulib
).
في هذه اللحظة ulib
, ، ال WriteString
يتم تنفيذ الطريقة في فئتين، SCREEN
و STREAM
.ال SCREEN
يستخدم الإصدار WriteConsoleW
مباشرةً، بحيث يتم عرض كافة أحرف Unicode بشكل صحيح.ال STREAM
يقوم الإصدار بتحويل نص Unicode إلى واحد من ثلاثة ترميزات مختلفة (_UseConsoleConversions
⇒ صفحة الرموز لوحدة التحكم (GetConsoleCP
), _UseAnsiConversions
⇒ صفحة رموز ANSI الافتراضية، وإلا ⇒ صفحة رموز OEM الافتراضية)، ثم يكتب ذلك.لا أعرف كيفية تغيير وضع التحويل، ولا أعتقد أنه يمكن تعطيل التحويل.
لقد ألقيت نظرة سريعة على هذا فقط، لذلك ربما يمكن للأرواح الأكثر ميلاً إلى المغامرة التحدث أكثر عنه!:-)
سيؤدي هذا إلى حفظ النتائج بتنسيق ASCII (الرمز القياسي الأمريكي لتبادل المعلومات) على سطح المكتب لديك، ولا يتعرف ASCII\ANSI على كل حرف دولي أو موسع:
tree /f > ascii.txt
سيؤدي هذا إلى تحويل نص ASCII إلى Unicode (يجب أن يسبق /c الأمر الفعلي):
cmd /u /c type ascii.txt > unicode.txt
فلماذا لا تفكر في ملف ascii كملف مؤقت وتحذفه؟
del ascii.txt
إذا كان يجب عليك وضع الكل في سطر واحد، فيمكنك استخدام:
tree /f > ascii.txt & cmd.exe /u /c type ascii.txt > unicode.txt & del ascii.txt
الجواب القصير هو انت لا تستطيع وهذا بسبب tree.com
هو تطبيق ANSI، حتى على نظام التشغيل Windows 7.
الحل الوحيد هو أن تكتب بنفسك tree
تطبيق.يمكنك أيضًا الإبلاغ عن خطأ إلى Microsoft، لكني أشك في أنهم ليسوا على علم به بالفعل.
يمكنك المحاولة
tree /A > output.txt
على الرغم من أنه يبدو مختلفًا عن خط CMD، إلا أنه لا يزال مقبولاً.:ص
لقد نجح هذا بالنسبة لي:
tree /f /a > %temp%\Listing >> files.txt
لقد نجحت في الحصول على الإخراج كما هو في وحدة التحكم، مع عدم تحويل كافة الأحرف غير ascii، عن طريق الإخراج إلى وحدة التحكم (فقط tree
) ثم النسخ منه (قائمة النظام -> تحرير -> تحديد، تحديد الكل، أدخل).يجب زيادة حجم المخزن المؤقت لوحدة التحكم مسبقًا، اعتمادًا على عدد الملفات/المجلدات، في خصائص وحدة التحكم (قائمة النظام -> الخصائص).طرق أخرى لم تنجح. tree|clip
, ، المذكور في منشور سابق، يحول الأحرف غير ascii إلى أحرف ascii نفسها tree>file.txt
.
لقد تمكنت من إخراج أحرف غير ascii بشكل صحيح من أمر الشجرة إلى ملف عبر خذ وحدة التحكم في الأوامر.
في TCC، اكتب "الخيار" وفي علامة التبويب الأولى حدد "إخراج Unicode".ثم قم بالتشغيل ببساطة
tree /f /a > output.txt
إجابة XP1 رائعة، ولكن بها تحذير بسيط:ترميز الإخراج هو UCS2-LE، بينما أفضل UTF8 (ملف أصغر وأكثر انتشارًا).
بعد كثيراً من البحث والخدش، يمكنني أخيرًا أن أقدم لك الأمر التالي، الذي ينتج ملف UTF8-BOM:
PowerShell -Command "TREE /F | Out-File output.txt -Encoding utf8"
إذا كان اسم ملف الإخراج يحتوي على مسافات:
PowerShell -Command "TREE /F | Out-File ""output file.txt"" -Encoding utf8"
شكرا جزيلا لهذا المقال: https://www.kongsli.net/2012/04/20/powershell-gotchas-redirect-to-file-encodes-in-unicode/
أيضًا، قمت شخصيًا بإنشاء الملفات التالية في PATH الخاص بي:
xtree.cmd
:
@IF [%1]==[] @(
ECHO You have to specify an output file.
GOTO :EOF
)
@PowerShell -Command "TREE | Out-File %1 -Encoding utf8"
xtreef.cmd
:
@IF [%1]==[] @(
ECHO You have to specify an output file.
GOTO :EOF
)
@PowerShell -Command "TREE /F | Out-File %1 -Encoding utf8"
وأخيرا بدلا من tree > output.txt
أنا فقط أفعل xtree output.txt
لقد استخدمت هذه الطريقة لفهرسة ما يقرب من 100 محرك أقراص SDRAM ومحركات أقراص USB المحمولة وقد عملت بشكل جيد.
من داخل الدوس ....
C:\doskey [أدخل] {لتمكين اختصارات لوحة المفاتيح المفيدة}
C: ree j:\ >> d:\MyCatalog.txt /a [أدخل] {j:= هو محرك أقراص USB الخاص بي؛d:= هو المكان الذي أريد الكتالوج فيه؛/a = شاهد المنشورات الأخرى على هذه الصفحة}