Сохранение результатов 'tree / f / a' в текстовый файл с поддержкой юникода - PullRequest
25 голосов
/ 26 сентября 2008

Я пытаюсь использовать команду дерева в командной строке Windows, чтобы сгенерировать текстовый файл со списком содержимого каталога, но когда я передаю вывод, символы юникода заполняются.

Вот команда, которую я использую:

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

Как я могу это исправить? В идеале текстовый файл должен быть точно таким же, как вывод в окне консоли.

Я попробовал предложение Криса Джестера-Янга (что случилось, вы удалили его, Крис?) О запуске командной строки с ключом / U, оно выглядело как раз то, что мне нужно, но, похоже, не работает. Я попытался открыть файл в VS2008 и в блокноте, и оба показывают одинаковые неправильные символы.

Ответы [ 12 ]

41 голосов
/ 26 июня 2012

Кто-то уже пробовал это:

tree /f /a |clip

Открыть блокнот, Ctrl + V, сохранить в блокноте как output.txt с поддержкой Юникода?

11 голосов
/ 26 сентября 2008

Если вы выводите как не-Unicode (что вы, очевидно, делаете), вы должны просмотреть текстовый файл, который вы создаете, используя ту же кодировку, которую использует окно консоли. Вот почему это выглядит правильно в консоли. В некоторых текстовых редакторах вы можете выбрать кодировку (или «кодовую страницу») при открытии файла. (Как выводить как Unicode, я не знаю. Cmd / U не делает то, что говорит документация.)

Кодировка консоли зависит от вашей установки Windows. Для меня это «Западноевропейский (DOS)» (или просто «MS-DOS») в Microsoft Word.

10 голосов
/ 12 апреля 2013

Использовать PowerShell:

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

EDIT:

Улучшенная и улучшенная версия для опытных пользователей

List tree menu working with Unicode

Контрольный пример:

$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 напрямую, чтобы все символы Юникода были корректно отображается. Версия STREAM преобразует текст Unicode в один из три разных кодировки (_UseConsoleConversions ⇒ кодовая страница консоли (GetConsoleCP), _UseAnsiConversions ⇒ кодовая страница ANSI по умолчанию, в противном случае ⇒ кодовая страница OEM по умолчанию), а затем записывает это.

Это означает, что мы не можем полагаться на получение символов из потока. Перенаправление файлов не будет работать. Мы должны полагаться на запись в консоль, чтобы получить символы Unicode.

Обходной путь, или взлом, состоит в том, чтобы записать дерево в консоль и затем сбросить буфер в файл.

Я написал сценарии для добавления контекстного меню дерева, когда вы щелкаете правой кнопкой по каталогам в Проводнике. Сохраните файлы в том же каталоге, а затем запустите 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
5 голосов
/ 18 апреля 2013

Это сохранит результаты как 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
5 голосов
/ 26 сентября 2008

Я решил, что мне нужно взглянуть на tree.com и выяснить, почему он не соблюдает настройки Unicode на консоли. Оказывается, что (как и многие файловые утилиты командной строки), он использует библиотеку с именем ulib.dll для всей печати (в частности, TREE::DisplayName вызывает WriteString в ulib).

Теперь в ulib метод WriteString реализован в двух классах SCREEN и STREAM. Версия SCREEN напрямую использует WriteConsoleW, поэтому все символы Юникода отображаются правильно. Версия STREAM преобразует текст Unicode в одну из трех разных кодировок (_UseConsoleConversions ⇒ кодовая страница консоли (GetConsoleCP), _UseAnsiConversions ⇒ кодовая страница ANSI по умолчанию, в противном случае ⇒ кодовая страница OEM по умолчанию), а затем записывает это. Я не знаю, как изменить режим преобразования, и я не верю, что преобразование можно отключить.

Я только кратко рассмотрел это, так что, возможно, более предприимчивые души могут говорить об этом больше! : -)

3 голосов
/ 25 января 2013

Вы можете попробовать

tree /A > output.txt

Хотя это выглядит не так, как в линии CMD, оно все же может быть приемлемым. : P

3 голосов
/ 04 мая 2010

Краткий ответ: , вы не можете , и это потому, что tree.com является приложением ANSI, даже в Windows 7.

Единственное решение - написать собственную реализацию tree. Также вы можете отправить сообщение об ошибке в Microsoft, но я сомневаюсь, что они еще не знают об этом.

2 голосов
/ 19 декабря 2011

Это сработало для меня:

tree /f /a > %temp%\Listing >> files.txt
0 голосов
/ 28 апреля 2019

Я использовал этот метод для каталогизации почти 100 флэш-накопителей SDRAM и USB, и он работал нормально.

Изнутри DOS ....

C: \ doskey [enter] {для включения удобных сочетаний клавиш}

C: \ tree j: \ >> d: \ MyCatalog.txt / a [enter] {j: = - это мой USB-накопитель; d: = где я хочу каталог; / a = посмотреть другие публикации на этой странице}

0 голосов
/ 10 июля 2018

Ответ 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...