Écrire un programme pour afficher le répertoire treehouse


9

À partir d'un répertoire (tel que C:/), à partir de stdin ou lu à partir d'un fichier, produisez une arborescence de répertoires, chaque fichier / dossier étant indenté en fonction de sa profondeur.

Exemple

Si j'ai un C:/lecteur qui ne contient que deux dossiers fooet bar, et barest vide pendant qu'il foocontient baz.txt, alors l'exécution avec entrée C:/produit:

C:/
    bar/
    foo/
        baz.txt

lors de l'exécution avec entrée C:/foo/devrait produire

foo/
    baz.txt

Comme il s'agit de codegolf, le nombre d'octets le plus bas l'emporte. Les extensions de fichiers (telles que baz.txt) sont facultatives. Notes supplémentaires: les fichiers cachés peuvent être ignorés, les répertoires doivent réellement exister, on peut supposer que les fichiers ne contiennent pas de caractères non imprimables ou de nouvelles lignes mais tous les autres caractères ASCII imprimables sont corrects (les noms de fichiers avec des espaces doivent être pris en charge). La sortie peut être écrite dans un fichier ou une sortie standard. Les indentations peuvent être constituées d'un caractère de tabulation ou de 4 espaces.


1
Remarque supplémentaire: cette question est mal formatée, donc un reformatage serait apprécié.
Mathime

Les langues qui n'ont pas accès aux fichiers sont-elles automatiquement disqualifiées?
Leaky Nun

Quels noms de fichiers doivent être pris en charge? Des fichiers avec des espaces dans leurs noms? Avec des nouvelles lignes? Avec des caractères non imprimables? Qu'en est-il des fichiers cachés (en commençant par .)?
Poignée de porte

1
@LeakyNun La sortie de la question de référence est un tableau de tableaux. Cette question nécessite une représentation de l'arborescence de répertoires à imprimer sur stdout.
Mathime

1
L'entrée peut-elle être un paramètre de chaîne d'une fonction?
mbomb007

Réponses:


10

bash, 61 58 54 octets

find "$1" -exec ls -Fd {} \;|perl -pe's|.*?/(?!$)|  |g'

Prend l'entrée comme argument de ligne de commande, sort sur STDOUT.

Notez que les espaces près de la fin avant le |gsont en fait un caractère de tabulation (SE les convertit en espaces lors de l'affichage des publications).

find              crawl directory tree recursively
"$1"              starting at the input directory
-exec             and for each file found, execute...
ls -Fd {} \;      append a trailing slash if it's a directory (using -F of ls)
|perl -pe         pipe each line to perl
'
s|                replace...
.*?/              each parent directory in the file's path...
(?!$)             that doesn't occur at the end of the string...
|    |            with a tab character...
g                 globally
'

Merci à @Dennis pour 4 octets!


2

Dyalog APL , 48 octets

(⊂∘⊃,1↓'[^\\]+\\'⎕R'    ')r[⍋↑r←⎕SH'dir/s/b ',⍞]

invite pour la saisie de caractères

'dir/s/b ', ajouter le texte

⎕SH exécuter en shell

r←stocker dans r

faire une liste de chaînes dans une matrice de caractères

indices de tri croissant

r[... ]réorganiser r [trié]

(... )sur la sortie standard de la commande shell, faites:

'[^\\]+\\'⎕R' ' regex remplace les séquences terminées par des antislashs de non-antislashs par quatre espaces

1↓ laisser tomber la première ligne

⊂∘⊃, ajouter le premier [ligne] ci-joint

Le résultat de la saisie de "\ tmp" à l'invite commence comme suit sur mon ordinateur:

C:\tmp\12u64
            keyboards64.msi
            netfx64.exe
            setup.exe
            setup_64_unicode.msi
            setup_dotnet_64.msi
        AdamsReg.reg
        AdamsReg.zip
        qa.dws
        ride-experimental
            win32
                d3dcompiler_47.dll
                icudtl.dat
                libEGL.dll


Les répertoires ne sont-ils pas censés avoir des caractères \ fin?
Neil


2

SML , 176 octets

open OS.FileSys;val! =chDir;fun&n w=(print("\n"^w^n);!n;print"/";c(openDir(getDir()))(w^"\t");!"..")and c$w=case readDir$of SOME i=>(&i w handle _=>();c$w)|x=>()fun%p=(&p"";!p)

Déclare (entre autres) une fonction %qui prend une chaîne en argument. Appelez avec % "C:/Some/Path";ou % (getDir());pour le répertoire actuel.

J'utilise le langage StandardML normalement utilisé de manière plutôt fonctionnelle, dont FileSysj'ai découvert la bibliothèque après avoir lu ce défi.

Les caractères spéciaux !, &, $et %ont pas de signification particulière dans la langue elle - même et sont simplement utilisés comme identifiants; cependant, ils ne peuvent pas être mélangés avec les identificateurs alphanumériques standard, ce qui permet de se débarrasser de certains espaces autrement nécessaires.

open OS.FileSys;
val ! = chDir;                       define ! as short cut for chDir

fun & n w = (                        & is the function name
                                     n is the current file or directory name
                                     w is a string containing the tabs
    print ("\n"^w^n);                ^ concatenates strings
    ! n;                             change in the directory, this throws an 
                                     exception if n is a file name
    print "/";                       if we are here, n is a directory so print a /
    c (openDir(getDir())) (w^"\t");  call c with new directory and add a tab to w
                                     to print the contents of the directory n
    ! ".."                           we're finished with n so go up again
)
and c $ w =                          'and' instead of 'fun' must be used 
                                     because '&' and 'c' are mutual recursive
                                     $ is a stream of the directory content
    case readDir $ of                case distinction whether any files are left
        SOME i => (                  yes, i is the file or directory name
            & i w handle _ => ();    call & to print i an check whether it's a 
                                     directory or not, handle the thrown exception 
            c $ w )                  recursively call c to check for more files in $
        | x    => ()                 no more files, we are finished

fun % p = (                          % is the function name, 
                                     p is a string containing the path
    & p "";                          call & to print the directory specified by p
                                     and recursively it's sub-directories
    ! p                              change back to path p due to the ! ".." in &
)

Peut être compilé comme ceci avec SML / NJ ou avec Moscow ML * en préfixant avec load"OS";.

* Voir mosml.org, ne peut pas publier plus de 2 liens.


1

C # (.NET Core) , 222 octets

namespace System.IO{class P{static int n;static void Main(String[]a){Console.WriteLine(new string('\t',n++)+Path.GetFileName(a[0]));try{foreach(var f in Directory.GetFileSystemEntries(a[0])){a[0]=f;Main(a);}}catch{}n--;}}}

Essayez-le en ligne!


Le non-golf:

using System.IO;
using System;

class P
{
    static int n=0;
    static void Main(String[] a)
    {
        for (int i=0;i<n;i++) Console.Write("\t");
        Console.WriteLine(Path.GetFileName(a[0]));
        n++;

        if(Directory.Exists(a[0]))
            foreach (String f in Directory.GetFileSystemEntries(a[0]))
                Main(new String[]{f});
        n--;
    }
}

C'est la première fois que je récursais une Mainfonction!

Je crois qu'une personne qui a une connaissance plus récente de C # peut jouer au golf plus, car je n'ai pas programmé sur C # depuis un certain temps!


0

PHP, 180 octets

  • premier argument: le chemin doit avoir une barre oblique de fin (ou barre oblique inverse)
  • deuxième argument: le niveau par défaut est NULLet sera interprété comme 0par str_repeat; lancera un avertissement s'il n'est pas fourni

function d($p,$e){$s=opendir($p);echo$b=str_repeat("\t",$e++),$e?basename($p)."/":$p,"
";while($f=readdir($s))echo preg_match("#^\.#",$f)?"":is_dir($p.$f)?d("$p$f/",$e):"$b\t$f
";}
  • affiche les fichiers et répertoires cachés, mais ne recrée pas les répertoires masqués,
    ajoute des parenthèses is_dir(...)?d(...):"..."pour supprimer les entrées masquées de la sortie (+2)
    remplace "#^\.#"par #^\.+$#pour afficher / recrée les entrées masquées mais ignore les entrées pointées (+2)
  • peut générer des erreurs lorsque les répertoires sont imbriqués trop profondément. Insérer closedir($s);avant la finale }à corriger (+13)
  • échouera si un répertoire contient une entrée sans nom, ajoutez false!==la condition while à corriger (+8)

avec glob, 182 octets (probablement 163 dans le futur php)

function g($p,$e){echo$b=str_repeat("\t",$e),$e++?basename($p)."/":$p,"
";foreach(glob(preg_replace("#[*?[]#","[$1]",$p)."*",2)as$f)echo is_dir($f)?g($f,$e):"$b\t".basename($f)."
";}
  • n'affiche pas ou n'invente pas les fichiers / répertoires cachés
  • 2signifie GLOB_MARK, ajoutera une barre oblique à tous les noms de répertoire, commels -F
  • les preg_replacecaractères spéciaux glob évadés que
    j'aurais pu abuser preg_quotepour cela (-19); mais cela échouerait sur les systèmes Windows, car la barre oblique inverse est le séparateur de répertoires.
  • php pourrait bientôt inclure une fonction glob_quote , qui permettra le même golf preg_quoteet fonctionner sur tous les systèmes.

avec des itérateurs, 183 octets
(enfin, pas purement des itérateurs: j'ai utilisé implicitement SplFileInfo::__toString()le golf $f->getBaseName()et $f->isDir()les anciennes fonctions PHP 4).

function i($p){echo"$p
";foreach($i=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($p),1)as$f)echo str_repeat("\t",1+$i->getDepth()),basename($f),is_dir($f)?"/":"","
";}
  • aucune barre oblique de fin requise
  • affiche et récursive les entrées cachées ( ls -a)
  • insérer ,4096ou ,FilesystemIterator::SKIP_DOTSavant ),1pour ignorer les entrées de points (+5) ( ls -A)
  • drapeau 1signifieRecursiveIteratorIterator::SELF_FIRST

0

PowerShell, 147 octets

param($a)function z{param($n,$d)ls $n.fullname|%{$f=$_.mode[0]-ne"d";Write-Host(" "*$d*4)"$($_.name)$(("\")[$f])";If(!$f){z $_($d+1)}}}$a;z(gi $a)1

Mec, je pense que PS devrait être capable de faire quelque chose comme la réponse bash, mais je ne propose rien de plus court que ce que j'ai ici.

Explication:

param($a)                     # assign first passed parameter to $a
function z{param($n,$d) ... } # declare function z with $n and $d as parameters
ls $n.fullname                # list out contents of directory
|%{ ... }                     # foreach
$f=$_.namde[0]-ne"d"          # if current item is a file, $f=true
Write-Host                    # writes output to the console
(" "*$d*4)                    # multiplies a space by the depth ($d) and 4
"$($_.name)$(("\")[$f])"      # item name + the trailing slash if it is a directory
;if(!$f){z $_($d+1)}          # if it is a directory, recursively call z
$a                            # write first directory to console
z(gi $a)1                     # call z with $a as a directoryinfo object and 1 as the starting depth

0

Python 2, 138 octets

Modifié à partir de cette réponse SO . Ce sont des onglets d'indentation, pas des espaces. L'entrée sera prise comme "C:/".

import os
p=input()
for r,d,f in os.walk(p):
    t=r.replace(p,'').count('/');print' '*t+os.path.basename(r)
    for i in f:print'   '*-~t+i

Essayez-le en ligne - C'est assez intéressant que je suis autorisé à parcourir le répertoire sur Ideone ...

Même longueur:

from os import*
p=input()
for r,d,f in walk(p):
    t=r.replace(p,'').count(sep);print' '*t+path.basename(r)
    for i in f:print'   '*-~t+i

0

Lot, 237 octets

@echo off
echo %~1\
for /f %%d in ('dir/s/b %1')do call:f %1 %%~ad "%%d"
exit/b
:f
set f=%~3
call set f=%%f:~1=%%
set i=
:l
set i=\t%i%
set f=%f:*\=%
if not %f%==%f:*\=% goto l
set a=%2
if %a:~0,1%==d set f=%f%\
echo %i%%f%

Où \ t représente le caractère de tabulation littéral. Cette version inclut des \s finaux sur les répertoires mais 41 octets peuvent être enregistrés s'ils ne sont pas nécessaires.


les `` `` derniers ne sont pas nécessaires
ASCII uniquement

0

Perl, 89 octets

C'est utile quand il y a un module de recherche dans la distribution principale. Le module File :: Find de Perl ne traverse pas l'arbre dans l'ordre alphabétique, mais la spécification ne l'a pas demandé.

/usr/bin/perl -MFile::Find -nE 'chop;find{postprocess,sub{--$d},wanted,sub{say" "x$d.$_,-d$_&&++$d&&"/"}},$_'

Le script proprement dit est de 76 octets, j'ai compté 13 octets pour les options de ligne de commande.



0

Java 8, 205 octets

import java.io.*;public interface M{static void p(File f,String p){System.out.println(p+f.getName());if(!f.isFile())for(File c:f.listFiles())p(c,p+"\t");}static void main(String[]a){p(new File(a[0]),"");}}

Il s'agit d'une soumission de programme complète qui prend en entrée son premier argument de ligne de commande (non explicitement autorisé, mais fait par de nombreux autres) et imprime la sortie en sortie standard.

Essayez-le en ligne (notez le nom différent de l'interface)

Non golfé

import java.io.*;

public interface M {
    static void p(File f, String p) {
        System.out.println(p + f.getName());
        if (!f.isFile())
            for (File c : f.listFiles())
                p(c, p + "\t");
    }

    static void main(String[] a) {
        p(new File(a[0]), "");
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.