Scrivere un programma per visualizzare la casa sull'albero delle directory


9

Data una directory (come C:/), data da stdin o letta da un file, produce un albero di directory, con ogni file / cartella rientrato in base alla sua profondità.

Esempio

Se ho C:/un'unità che contiene solo due cartelle fooe bar, ed barè vuota mentre foocontiene baz.txt, allora l'esecuzione con input C:/produce:

C:/
    bar/
    foo/
        baz.txt

durante l'esecuzione con input C:/foo/dovrebbe produrre

foo/
    baz.txt

Poiché questo è codegolf, vince il conteggio di byte più basso. Le estensioni dei file (come baz.txt) sono opzionali. Note extra: i file nascosti possono essere ignorati, le directory devono effettivamente esistere, si può presumere che i file non contengano caratteri non stampabili o nuove righe ma tutti gli altri caratteri ASCII stampabili vanno bene (i nomi dei file con spazi devono essere supportati). L'output può essere scritto su file o stdout. I rientri possono essere costituiti da un carattere di tabulazione o da 4 spazi.


1
Nota extra: questa domanda è mal formattata, quindi una formattazione sarebbe apprezzata.
Mathime,

Le lingue che non hanno accesso ai file vengono automaticamente squalificate?
Leaky Nun,

Quali nomi di file devono essere supportati? File con spazi nei loro nomi? Con le nuove righe? Con caratteri non stampabili? Che dire dei file nascosti (a partire da .)?
Maniglia della porta

1
@LeakyNun L'output della domanda di riferimento è una matrice di array. Questa domanda richiede che una rappresentazione dell'albero delle directory sia stampata su stdout.
Mathime,

1
L'input può essere un parametro stringa per una funzione?
mbomb007,

Risposte:


10

bash, 61 58 54 byte

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

Accetta input come argomento della riga di comando, output su STDOUT.

Si noti che gli spazi vicino alla fine prima che |gsiano effettivamente un carattere di tabulazione (SE li converte in spazi durante la visualizzazione dei messaggi).

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
'

Grazie a @Dennis per 4 byte!


2

Dyalog APL , 48 byte

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

richiedere l'immissione di caratteri

'dir/s/b ', anteporre testo

⎕SH eseguire in shell

r←negozio in r

crea un elenco di stringhe in una matrice di caratteri

indici per l'ordinamento crescente

r[... ]riordina r [ordinato]

(... )sullo standard out of the shell command, esegui:

'[^\\]+\\'⎕R' ' regex sostituisce le esecuzioni di non barre rovesciate con barra rovesciata con quattro spazi

1↓ rilascia la prima riga

⊂∘⊃, anteporre la prima riga [allegata]

Il risultato dell'inserimento di "\ tmp" nel prompt inizia come segue sul mio computer:

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


Le directory non dovrebbero avere trailing \ caratteri?
Neil,


2

SML , 176 byte

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)

Dichiara (tra gli altri) una funzione %che accetta una stringa come argomento. Chiama con % "C:/Some/Path";o % (getDir());per la directory corrente.

Sto usando il linguaggio StandardML normalmente utilizzato in modo piuttosto funzionale il cui FileSys-Library ho scoperto dopo aver letto questa sfida.

I caratteri speciali !, &, $e %non hanno alcun significato speciale nel linguaggio stesso e sono semplicemente utilizzati come identificatori; tuttavia non possono essere mischiati con gli identificatori alfanumerici standard che consentono di eliminare alcuni spazi altrimenti necessari.

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

Può essere compilato in questo modo con SML / NJ o con Moscow ML * prefissando con load"OS";.

* Vedi mosml.org, non posso pubblicare più di 2 link.


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

Provalo online!


Il ungolf:

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

La prima volta che ho mai ripreso una Mainfunzione!

Credo che una persona che abbia una conoscenza più approfondita del C # possa giocarci di più, dato che non programmavo su C # da un po 'di tempo!


0

PHP, 180 byte

  • primo argomento: il percorso deve avere una barra finale (o barra rovesciata)
  • secondo argomento: il livello predefinito è NULLe sarà interpretato come 0da str_repeat; lancerà un avviso se non fornito

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
";}
  • visualizza i file e le directory nascosti, ma non ricorre alle directory nascoste
    aggiungendo parentesi is_dir(...)?d(...):"..."per rimuovere le voci nascoste dall'output (+2)
    sostituisci "#^\.#"con #^\.+$#per visualizzare / ricorrere alle voci nascoste ma salta le voci punto (+2)
  • può generare errori quando le directory sono nidificate troppo in profondità. Inserisci closedir($s);prima della finale }da correggere (+13)
  • fallirà se una directory contiene una voce senza nome, antepone false!==alla condizione while da correggere (+8)

con glob, 182 byte (probabilmente 163 in futuro 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)."
";}
  • non visualizza né fa ricorso a file / directory nascosti
  • 2sta per GLOB_MARKaggiungere una barra a tutti i nomi di directory, come fals -F
  • i preg_replacecaratteri speciali glob di escape che
    avrei potuto abusare preg_quotedi questo (-19); ma ciò fallirebbe sui sistemi Windows, poiché la barra rovesciata è il separatore di directory lì.
  • php potrebbe presto includere una funzione glob_quote , che consentirà lo stesso golf preg_quotee funzionerà su tutti i sistemi.

con iteratori, 183 byte
(beh, non puramente iteratori: ho usato implicitamente il SplFileInfo::__toString()golf $f->getBaseName()e $f->isDir()le vecchie funzioni di 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)?"/":"","
";}
  • nessuna barra finale richiesta
  • visualizza e recluta voci nascoste ( ls -a)
  • inserire ,4096o ,FilesystemIterator::SKIP_DOTSprima ),1di saltare le voci punto (+5) ( ls -A)
  • bandiera 1sta perRecursiveIteratorIterator::SELF_FIRST

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

Amico, sento che PS dovrebbe essere in grado di fare qualcosa come la risposta bash, ma non sto inventando niente di più corto di quello che ho qui.

Spiegazione:

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 byte

Modificato da questa risposta SO . Quelle sono schede per il rientro, non spazi. L'input verrà preso come "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

Provalo online - È abbastanza interessante che mi permetta di sfogliare la directory su Ideone ...

Stessa lunghezza:

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

Lotto, 237 byte

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

Dove \ t rappresenta il carattere di tabulazione letterale. Questa versione include messaggi finali \sulle directory ma 41 byte possono essere salvati se non necessari.


non sono necessari i post finali
solo ASCII il

0

Perl, 89 byte

È utile quando c'è un modulo find nella distribuzione core. Il file Perl :: Trova il modulo non attraversa l'albero in ordine alfabetico, ma le specifiche non lo richiedono.

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

Lo script corretto è di 76 byte, ho contato 13 byte per le opzioni della riga di comando.


0

Tcl , 116 byte

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

Provalo online!


0

Java 8, 205 byte

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

Questa è una presentazione completa del programma che prende input dal suo primo argomento da riga di comando (non esplicitamente permesso, ma fatto da molti altri) e stampa l'output allo standard out.

Provalo online (annota il nome di un'altra interfaccia)

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]), "");
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.