Schreiben Sie ein Programm zum Anzeigen des Verzeichnisbaumhauses

9

C:/Erstellen Sie bei einem gegebenen Verzeichnis (z. B. ), das von stdin angegeben oder aus einer Datei gelesen wurde, einen Verzeichnisbaum, wobei jede Datei / jeder Ordner basierend auf ihrer Tiefe eingerückt wird.

Beispiel

Wenn ich ein C:/Laufwerk , das nur enthält zwei Ordner foound bar, und barist leer , während fooenthält baz.txt, dann läuft mit Eingang C:/erzeugt:

C:/
    bar/
    foo/
        baz.txt

beim laufen mit eingabe C:/foo/sollte produzieren

foo/
    baz.txt

Da dies Codegolf ist, gewinnt die niedrigste Byteanzahl. Die Dateierweiterungen (z. B. baz.txt) sind optional. Zusätzliche Hinweise: Versteckte Dateien können ignoriert werden, Verzeichnisse müssen tatsächlich vorhanden sein, es kann davon ausgegangen werden, dass Dateien keine nicht druckbaren Zeichen oder neuen Zeilen enthalten, aber alle anderen druckbaren ASCII-Zeichen sind in Ordnung (Dateinamen mit Leerzeichen müssen unterstützt werden). Die Ausgabe kann in eine Datei oder in eine Standardausgabe geschrieben werden. Die Einrückungen können entweder aus einem Tabulatorzeichen oder 4 Leerzeichen bestehen.

Mathime
quelle
1
Zusätzlicher Hinweis: Diese Frage ist schlecht formatiert, daher wäre eine Neuformatierung wünschenswert.
Mathime
Werden Sprachen, die keinen Zugriff auf Dateien haben, automatisch disqualifiziert?
Undichte Nonne
Welche Dateinamen müssen unterstützt werden? Dateien mit Leerzeichen im Namen? Mit Zeilenumbrüchen? Mit nicht druckbaren Zeichen? Was ist mit versteckten Dateien (beginnend mit .)?
Türknauf
1
@LeakyNun Die Ausgabe der Referenzfrage ist ein Array von Arrays. Diese Frage erfordert eine Darstellung des Verzeichnisbaums, der auf stdout gedruckt werden soll.
Mathime
1
Kann die Eingabe ein Zeichenfolgenparameter für eine Funktion sein?
mbomb007

Antworten:

10

Bash, 61 58 54 Bytes

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

Nimmt die Eingabe als Befehlszeilenargument und gibt sie in STDOUT aus.

Beachten Sie, dass die Leerzeichen am Ende vor dem |gtatsächlich ein Tabulatorzeichen sind (SE konvertiert sie in Leerzeichen, wenn Beiträge angezeigt werden).

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
'

Danke an @Dennis für 4 Bytes!

Türknauf
quelle
2

Dyalog APL , 48 Bytes

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

Eingabeaufforderung zur Zeicheneingabe

'dir/s/b ', Text voranstellen

⎕SH in Shell ausführen

r←speichern in r

Erstellen Sie eine Liste der Zeichenfolgen in der Zeichenmatrix

Indizes für aufsteigende Sortierung

r[... ]neu ordnen r [sortiert]

(... )auf dem Standard aus dem Shell-Befehl:

'[^\\]+\\'⎕R' ' Regex ersetzt Backslash-terminierte Läufe von Nicht-Backslashes durch vier Leerzeichen

1↓ Lassen Sie die erste Zeile fallen

⊂∘⊃, Stellen Sie die beiliegende erste [Zeile] voran.

Das Ergebnis der Eingabe von "\ tmp" in die Eingabeaufforderung beginnt auf meinem Computer wie folgt:

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

Adam
quelle
Sollen die Verzeichnisse nicht nachgestellte \ Zeichen haben?
Neil
2

SML , 176 Bytes

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)

Deklariert (unter anderem) eine Funktion, %die eine Zeichenfolge als Argument verwendet. Rufen Sie mit % "C:/Some/Path";oder % (getDir());für das aktuelle Verzeichnis.

Ich verwende die normalerweise eher funktional verwendete Sprache StandardML, deren FileSysBibliothek ich nach dem Lesen dieser Herausforderung entdeckt habe.

Die Sonderzeichen !, &, $und %haben keine besondere Bedeutung in der Sprache selbst und werden einfach als Bezeichner verwendet; Sie können jedoch nicht mit den alphanumerischen Standardkennungen gemischt werden, wodurch einige ansonsten benötigte Leerzeichen entfernt werden können.

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 &
)

Kann so mit SML / NJ oder mit Moscow ML * durch Präfixieren mit kompiliert werden load"OS";.

* Siehe mosml.org, kann nicht mehr als 2 Links posten.

Laikoni
quelle
1

C # (.NET Core) , 222 Byte

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--;}}}

Probieren Sie es online aus!


Der Unwolf:

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--;
    }
}

Zum ersten Mal habe ich eine MainFunktion rekursiv gemacht !

Ich glaube, eine Person, die frischere Kenntnisse über C # hat, kann mehr Golf spielen, da ich einige Zeit nicht auf C # programmiert habe!

Sergiol
quelle
0

PHP, 180 Bytes

  • erstes Argument: Pfad muss einen abschließenden Schrägstrich (oder Backslash) haben
  • zweites Argument: Stufe standardmäßig auf NULLund wird als interpretiert werden , 0durch str_repeat; wird eine Warnung auslösen, wenn nicht angegeben

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
";}
  • Zeigt versteckte Dateien und Verzeichnisse an, aber nicht wiederkehrende versteckte Verzeichnisse. Fügen
    Sie Klammern hinzu is_dir(...)?d(...):"...", um versteckte Einträge aus der Ausgabe zu entfernen (+2).
    Ersetzen Sie diese "#^\.#"durch #^\.+$#, um versteckte Einträge anzuzeigen / wiederzuverwenden, aber überspringen Sie Punkteinträge (+2).
  • kann Fehler auslösen, wenn Verzeichnisse zu tief verschachtelt sind. Legen Sie closedir($s);vor dem Finale }zu fixieren (+13)
  • schlägt fehl, wenn ein Verzeichnis einen Eintrag ohne Namen enthält. Stellen Sie false!==der while-Bedingung vor, die behoben werden soll (+8).

mit glob 182 bytes (wahrscheinlich 163 in zukünftigen 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)."
";}
  • zeigt keine versteckten Dateien / Verzeichnisse an oder verwendet sie nicht
  • 2steht für GLOB_MARK, wird wie bei allen Verzeichnisnamen einen Schrägstrich anhängenls -F
  • die preg_replaceEscape-Glob-Sonderzeichen, die
    ich dafür hätte missbrauchen preg_quotekönnen (-19); Dies würde jedoch auf Windows-Systemen fehlschlagen, da der Backslash dort das Verzeichnis-Trennzeichen ist.
  • PHP könnte bald eine Funktion glob_quote enthalten , die das gleiche Golfen wie preg_quoteund auf allen Systemen ermöglicht.

mit Iteratoren 183 Bytes
(na ja, nicht nur Iteratoren: Ich habe implizit SplFileInfo::__toString()Golf $f->getBaseName()und $f->isDir()die alten PHP 4-Funktionen verwendet.)

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)?"/":"","
";}
  • Kein abschließender Schrägstrich erforderlich
  • zeigt versteckte Einträge an und rekursiert sie ( ls -a)
  • Einfügen ,4096oder ,FilesystemIterator::SKIP_DOTSvorher ),1, um Punkteinträge zu überspringen (+5) ( ls -A)
  • Flagge 1steht fürRecursiveIteratorIterator::SELF_FIRST
Titus
quelle
0

PowerShell, 147 Byte

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

Mann, ich denke, PS sollte in der Lage sein, so etwas wie die Bash-Antwort zu machen, aber ich habe nichts kürzeres als das, was ich hier habe.

Erläuterung:

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
ThePoShWolf
quelle
0

Python 2, 138 Bytes

Geändert von dieser SO-Antwort . Dies sind Tabulatoren für Einrückungen, keine Leerzeichen. Eingabe wird wie genommen "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

Probieren Sie es online aus - Es ist ziemlich interessant, dass ich das Verzeichnis auf Ideone durchsuchen darf ...

Die gleiche Länge:

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
mbomb007
quelle
0

Stapel, 237 Bytes

@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%

Wobei \ t das Literal-Tabulatorzeichen darstellt. Diese Version enthält nachgestellte \s in Verzeichnissen, aber 41 Bytes können gespeichert werden, wenn sie nicht benötigt werden.

Neil
quelle
Die nachfolgenden `\` s werden nicht benötigt
ASCII-
0

Perl, 89 Bytes

Dies ist nützlich, wenn die Kerndistribution ein Suchmodul enthält. Perls File :: Find-Modul durchläuft den Baum nicht in alphabetischer Reihenfolge, aber die Spezifikation hat nicht danach gefragt.

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

Das eigentliche Skript ist 76 Bytes, ich habe 13 Bytes für die Befehlszeilenoptionen gezählt.

Daniel
quelle
0

Tcl , 116 Bytes

proc L f {puts [string repe \t [expr [incr ::n]-1]][file ta $f];lmap c [glob -n -d $f *] {L $c};incr ::n -1}
L $argv

Probieren Sie es online aus!

Sergiol
quelle
0

Java 8, 205 Bytes

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]),"");}}

Dies ist eine vollständige Programmübermittlung, die Eingaben von ihrem ersten Befehlszeilenargument (nicht explizit zulässig, aber von vielen anderen ausgeführt) übernimmt und die Ausgabe als Standard aus druckt.

Probieren Sie es online aus (beachten Sie den anderen Namen der Benutzeroberfläche)

Ungolfed

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]), "");
    }
}
Jakob
quelle