web-dev-qa-db-fra.com

Enregistrement des résultats 'tree/f/a "dans un fichier texte avec prise en charge unicode

J'essaie d'utiliser la commande tree dans une ligne de commande Windows pour générer un fichier texte répertoriant le contenu d'un répertoire, mais lorsque je rediffuse la sortie, les caractères unicode sont remplis.

Voici la commande que j'utilise:

tree /f /a > output.txt

Les résultats dans la fenêtre de la console sont corrects:

\--- 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 

Mais le fichier texte n'est pas bon:

\--- 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 

Comment puis-je réparer cela? Idéalement, le fichier texte devrait être identique à la sortie dans la fenêtre de la console.

J'ai essayé la suggestion de Chris Jester-Young (que s'est-il passé, l'avez-vous supprimée, Chris?) D'exécuter la ligne de commande avec le commutateur/U? J'ai essayé d'ouvrir le fichier à la fois dans VS2008 et dans le Bloc-notes et les deux affichent les mêmes caractères incorrects.

23
Paul Batum

Avez-vous déjà essayé ceci:

tree /f /a |clip

Ouvrez le bloc-notes, ctrl + V, enregistrez-le dans le bloc-notes en tant que output.txt avec le support unicode?

38
Ricardo Bohner

Si vous exportez en mode non-Unicode (ce que vous avez apparemment fait), vous devez afficher le fichier texte créé en utilisant le même codage que celui utilisé par la fenêtre de la console. C'est pourquoi cela semble correct dans la console. Dans certains éditeurs de texte, vous pouvez choisir un codage (ou "page de code") lorsque vous ouvrez un fichier. (Comment sortir en Unicode, je ne sais pas. Cmd/U ne fait pas ce que dit la documentation.)

Le codage de la console dépend de votre installation Windows. Pour moi, c'est "Western European (DOS)" (ou simplement "MS-DOS") dans Microsoft Word.

11
bzlm

Utilisez PowerShell:

powershell -command "tree /f > tree.txt"

Cas de test:

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"

Sortie:

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

MODIFIER:

Version améliorée et améliorée pour les utilisateurs expérimentés

 List tree menu working with Unicode

Cas de test:

$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"

De sa réponse , @Chris Jester-Young a écrit:

Maintenant, dans ulib, la méthode WriteString est implémentée en deux classes, SCREEN et STREAM. La version SCREEN utilise WriteConsoleW directement, afin que tous les caractères Unicode soient correctement enregistrés affiché. La version STREAM convertit le texte Unicode en un trois encodages différents (_UseConsoleConversions ⇒ page de code console (GetConsoleCP), _UseAnsiConversions ⇒ page de code ANSI par défaut, sinon ⇒ page de code OEM par défaut), puis écrit ceci.

Cela signifie que nous ne pouvons pas compter sur l’obtention des caractères d’un flux. Les redirections de fichiers ne fonctionneront pas. Nous devons nous fier à l’écriture sur la console pour obtenir les caractères Unicode.

La solution de contournement, ou hack, consiste à écrire l'arborescence sur la console, puis à vider le tampon dans un fichier.

J'ai écrit les scripts pour ajouter le menu contextuel de l'arborescence lorsque vous cliquez avec le bouton droit sur des répertoires dans Explorer. Enregistrez les fichiers dans le même répertoire, puis exécutez Install list menu.bat en tant qu’administrateur à installer.

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
10
XP1

Cela enregistrera les résultats sous le format ASCII (code américain standard pour l'échange d'informations) sur votre bureau. ASCII\ANSI ne reconnaît pas tous les caractères internationaux ou étendus:

tree /f > ascii.txt

Ceci convertira votre texte ASCII en Unicode (/ c doit précéder la commande réelle):

cmd /u /c type ascii.txt > unicode.txt

Alors, pourquoi ne pas simplement considérer le fichier ascii comme un fichier temporaire et le supprimer?

del ascii.txt

Si vous devez tout mettre en ligne, vous pouvez utiliser:

tree /f > ascii.txt & cmd.exe /u /c type ascii.txt > unicode.txt & del ascii.txt
5
Ricardo Bohner

J'ai décidé de consulter tree.com et de comprendre pourquoi il ne respecte pas le paramètre Unicode de la console. Il s'avère que (comme beaucoup d'utilitaires de fichier de ligne de commande), il utilise une bibliothèque appelée ulib.dll pour effectuer toutes les impressions (plus précisément, TREE::DisplayName appelle WriteString dans ulib).

Désormais, dans ulib, la méthode WriteString est implémentée dans deux classes, SCREEN et STREAM. La version SCREEN utilise directement WriteConsoleW, de sorte que tous les caractères Unicode sont correctement affichés. La version STREAM convertit le texte Unicode en un des trois codages différents (_UseConsoleConversions ⇒ page de code de la console (GetConsoleCP), _UseAnsiConversions ⇒ page de code ANSI par défaut, sinon ⇒ page de code OEM par défaut), puis l’écrit. Je ne sais pas comment changer le mode de conversion et je ne crois pas que la conversion puisse être désactivée.

Je n’ai que brièvement regardé cela, alors peut-être que des âmes plus aventureuses pourront en parler davantage! :-)

5
Chris Jester-Young

La réponse courte est vous ne pouvez pas et ceci est dû au fait que tree.com est une application ANSI, même sous Windows 7.

La seule solution consiste à écrire votre propre implémentation tree. Vous pouvez également signaler un bogue à Microsoft, mais je doute qu'ils ne soient pas déjà au courant.

3
sorin

Tu peux essayer 

tree /A > output.txt

Bien que cela semble différent de la ligne CMD, cela pourrait quand même être acceptable. : P

3
Kenn

Cela a fonctionné pour moi: 

tree /f /a > %temp%\Listing >> files.txt
2
Chris

La réponse de XP1 est excellente, mais avec un inconvénient mineur: le codage de sortie est UCS2-LE, alors que je préférerais UTF8 (taille de fichier plus petite et plus répandue).

Après beaucoup de recherche et de grattage, je peux enfin vous présenter la commande suivante, qui produit un fichier UTF8-BOM:

PowerShell -Command "TREE /F | Out-File output.txt -Encoding utf8"

Si le nom du fichier de sortie contient des espaces:

PowerShell -Command "TREE /F | Out-File ""output file.txt"" -Encoding utf8"

Un grand merci à cet article: https://www.kongsli.net/2012/04/20/20/powershell-gotchas-redirect-to-file-encodes-in-unicode/


De plus, personnellement, j'ai créé les fichiers suivants dans mon 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"

Enfin, au lieu de tree > output.txt je ne fais que xtree output.txt

0
Gras Double

J'ai réussi à obtenir le résultat tel qu'il est dans la console, avec tous les caractères non-ASCII non convertis, en envoyant le résultat sur la console (juste tree) puis en le copiant (menu système -> Édition -> Marquer, en sélectionnant tout ). La taille de la mémoire tampon de la console doit être augmentée à l'avance, en fonction du nombre de fichiers/dossiers, dans les propriétés de la console (menu système -> Propriétés). Les autres moyens ne fonctionnaient pas. tree|clip, mentionné dans un précédent article, convertit les caractères non ascii en caractères ascii identiques à tree>file.txt.

0
Miguel

J'ai réussi à sortir correctement les caractères non-ASCII de la commande tree dans un fichier via Take Command Console .

Dans le TCC, tapez "option" et sur le premier onglet, sélectionnez "Sortie Unicode". Puis lancez simplement 

tree /f /a > output.txt
0
user1959451