Enregistrement des résultats ‘tree / f / a “dans un fichier texte avec un support 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 diffuse la sortie, les caractères Unicode sont surchargés.

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, SVG g.ogg
         K tai Tam s - 09 Z £ zmara.ogg

Comment puis-je réparer cela? Idéalement, le fichier texte serait exactement le même que le résultat dans la fenêtre de la console.

J’ai essayé la suggestion de Chris Jester-Young (qu’est-ce qui s’est passé, avez-vous supprimé Chris?) De l’exécution de la ligne de commande avec le commutateur / U, cela ressemblait exactement à ce dont j’avais besoin mais cela ne semble pas fonctionner. J’ai essayé d’ouvrir le fichier à la fois dans VS2008 et le bloc-notes et les deux affichent les mêmes caractères incorrects.

Avez-vous déjà essayé ceci:

 tree /f /a |clip 

Ouvrez le bloc-notes, ctrl + V, enregistrez-le dans le bloc-notes sous le nom output.txt avec un support Unicode?

Si vous produisez en tant que non-Unicode (ce que vous faites apparemment), vous devez afficher le fichier texte que vous créez en utilisant le même encodage que celui utilisé par la fenêtre de la console. C’est pourquoi il semble correct dans la console. Dans certains éditeurs de texte, vous pouvez choisir un encodage (ou “page de codes”) 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, il s’agit de “Western European (DOS)” (ou simplement “MS-DOS”) dans Microsoft Word.

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

Menu arborescence de liste fonctionnant avec 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 WriteSsortingng est implémentée dans deux classes, SCREEN et STREAM . La version SCREEN utilise directement WriteConsoleW , donc tous les caractères Unicode s’affichent correctement. La version STREAM convertit le texte Unicode en 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 écrit ceci.

Cela signifie que nous ne pouvons pas compter sur l’obtention des caractères d’un stream. Les redirections de fichiers ne fonctionneront pas. Nous devons compter sur 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 append le menu contextuel de l’arborescence lorsque vous cliquez avec le bouton droit sur des répertoires dans l’Explorateur. Enregistrez les fichiers dans le même répertoire, puis exécutez la Install list menu.bat 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)] [ssortingng] $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-ssortingng } 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.SsortingngBuilder $characters = new-object System.Text.SsortingngBuilder 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.toSsortingng()) | out-null $characters.length = 0 } $lines.toSsortingng() -replace '[ \0]*\r?\n', "`r`n" } function main { param( [parameter(mandatory = $true)] [ssortingng] $type = $null, [parameter(mandatory = $true)] [ssortingng] $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 

J’ai décidé de jeter un coup d’œil à tree.com et de comprendre pourquoi il ne respectait pas le paramètre Unicode de la console. Il s’avère que (comme la plupart des utilitaires de fichiers en ligne de commande), il utilise une bibliothèque appelée ulib.dll pour effectuer toutes les impressions (spécifiquement, TREE::DisplayName appelle WriteSsortingng dans ulib ).

Maintenant, dans ulib , la méthode WriteSsortingng est implémentée dans deux classes, SCREEN et STREAM . La version SCREEN utilise directement WriteConsoleW , donc tous les caractères Unicode s’affichent correctement. La version STREAM convertit le texte Unicode en 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 écrit ceci. Je ne sais pas comment changer le mode de conversion, et je ne pense pas que la conversion peut être désactivée.

Je ne l’ai regardé que brièvement, alors peut-être que des âmes plus aventureuses en parleront davantage! 🙂

Cela enregistrera les résultats sous forme de code ASCII (American Standard Code for Information Interchange) sur votre bureau, ASCII \ ANSI ne reconnaît pas tous les caractères internationaux ou étendus:

 tree /f > ascii.txt 

Cela 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 penser au fichier ASCII comme fichier temporaire et le supprimer?

 del ascii.txt 

Si vous devez tout mettre dans une seule ligne, vous pouvez utiliser:

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

La réponse courte est que vous ne pouvez pas et c’est parce que tree.com est une application ANSI, même sur Windows 7.

La seule solution consiste à écrire votre propre implémentation d’ tree . Aussi, vous pourriez déposer un bogue pour Microsoft, mais je doute qu’ils ne soient pas déjà au courant.

Tu peux essayer

 tree /A > output.txt 

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

Cela a fonctionné pour moi:

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

J’ai réussi à obtenir la sortie telle qu’elle est dans la console, avec tous les caractères non-ascii non convertis, en les exportant vers la console (juste l’ tree ) puis en les copiant (menu système -> Modifier -> Marquer, tout sélectionner, Entrer ). La taille de la mémoire tampon de la console doit être augmentée au préalable, 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 article précédent, convertit les caractères non-ascii en caractères ascii identiques à tree>file.txt .

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

Dans TCC, tapez “option” et sur le premier onglet sélectionnez “Sortie Unicode”. Alors lancez simplement

 tree /f /a > output.txt 

La réponse de XP1 est géniale, mais elle comportait une petite mise en garde: l’encodage de sortie est UCS2-LE, alors que je préfère UTF8 (taille de fichier plus petite et plus répandue).

Après beaucoup de recherches et de grattements, 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 comporte des espaces:

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

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


En outre, 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 fais juste xtree output.txt