Napisz program do wyświetlania katalogu domku na drzewie


9

Biorąc pod uwagę katalog (taki jak C:/), podany ze standardowego wejścia lub odczytany z pliku, stwórz drzewo katalogów, z każdym wcięciem pliku / folderu na podstawie jego głębokości.

Przykład

Jeśli mam C:/dysk, który zawiera tylko dwa foldery fooi bar, i barjest pusty, gdy foozawiera baz.txt, wówczas uruchomiony z wejściem C:/produkuje:

C:/
    bar/
    foo/
        baz.txt

podczas pracy z nakładem C:/foo/powinien produkować

foo/
    baz.txt

Ponieważ jest to kodegolf, wygrywa najmniejsza liczba bajtów. Rozszerzenia plików (takie jak baz.txt) są opcjonalne. Dodatkowe uwagi: ukryte pliki można zignorować, katalogi muszą faktycznie istnieć, można założyć, że pliki nie zawierają znaków niedrukowalnych ani nowych wierszy, ale wszystkie inne znaki ASCII do wydruku są w porządku (nazwy plików ze spacjami muszą być obsługiwane). Dane wyjściowe można zapisać do pliku lub standardowego wyjścia. Wcięcia mogą składać się ze znaku tabulacji lub 4 spacji.


1
Dodatkowa uwaga: to pytanie jest źle sformatowane, dlatego mile widziane byłoby sformatowanie.
— Mathime,

Czy języki, które nie mają dostępu do plików, są automatycznie dyskwalifikowane?
— Leaky Nun

Jakie nazwy plików muszą być obsługiwane? Pliki ze spacjami w swoich nazwach? Z nowymi liniami? Z drukowanymi postaciami? Co z ukrytymi plikami (zaczynając od .)?
— Klamka

1
@LeakyNun Dane wyjściowe pytania referencyjnego to tablica tablic. To pytanie wymaga przedstawienia drzewa katalogów do wydrukowania na standardowe wyjście.
— Mathime,

1
Czy wejście może być parametrem ciągu funkcji?
— mbomb007

Odpowiedzi:


10

bash, 61 58 54 bajtów

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

Pobiera dane wejściowe jako argument wiersza poleceń, dane wyjściowe w STDOUT.

Zauważ, że spacje na końcu przed |gznakiem są w rzeczywistości znakiem tabulacji (SE konwertuje je na spacje podczas wyświetlania postów).

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
'

Dzięki @Dennis za 4 bajty!


2

Dyalog APL , 48 bajtów

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

⍞ monit o wprowadzenie znaku

'dir/s/b ', poprzedzać tekst

⎕SH wykonać w powłoce

r←przechowywać w r

↑ zrobić listę ciągów znaków w macierz znaków

⍋ wskaźniki do sortowania rosnącego

r[... ]zmienić kolejność r [posortowane]

(... )na standardowym poleceniu poza powłoką wykonaj:

'[^\\]+\\'⎕R' ' regex zastępuje zakończone odwrotnym ukośnikiem przebiegi nie odwrotnych ukośników czterema spacjami

1↓ upuść pierwszą linię

⊂∘⊃, dodaj załączony pierwszy [wiersz]

Wynik wprowadzenia „\ tmp” do monitu zaczyna się na moim komputerze w następujący sposób:

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

⋮


Czy katalogi nie powinny zawierać znaków końcowych \?
— Neil


2

SML , 176 bajtów

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)

Deklaruje (między innymi) funkcję, %która przyjmuje ciąg znaków jako argument. Zadzwoń z % "C:/Some/Path";lub % (getDir());do bieżącego katalogu.

Używam normalnie raczej funkcjonalnie używanego języka StandardML, którego FileSys-Bibliotekę odkryłem po przeczytaniu tego wyzwania.

Znaki specjalne !, &, $i %nie mają szczególnego znaczenia w samym języku, a są po prostu wykorzystywane jako identyfikatory; nie można ich jednak łączyć ze standardowymi identyfikatorami alfanumerycznymi, co pozwala pozbyć się całkiem potrzebnych spacji.

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

Może być skompilowany w ten sposób z SML / NJ lub z Moscow ML * przez prefiks z load"OS";.

* Zobacz mosml.org, nie można opublikować więcej niż 2 linków.


1

C # (.NET Core) , 222 bajty

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

Wypróbuj online!


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

Po raz pierwszy w historii zawróciłem Mainfunkcję!

Wierzę, że osoba, która ma świeższą wiedzę na temat C #, może bardziej grać w golfa, ponieważ przez pewien czas nie programowałem na C #!


0

PHP, 180 bajtów

  • pierwszy argument: ścieżka musi mieć ukośnik końcowy (lub ukośnik odwrotny)
  • Drugi argument: domyślnie poziomie, aby NULLi będzie interpretowany jako 0o str_repeat; wyśle ​​ostrzeżenie, jeśli nie zostanie podane

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
";}
  • wyświetla ukrytych plików i katalogów, ale nie recurse ukrytych katalogów
    dodać nawiasy wokół is_dir(...)?d(...):"..."aby usunąć ukryte dane z wyjścia (+2)
    zastąpić "#^\.#"ze #^\.+$#na wyświetlaczu / recurse ukryte wpisy ale pominąć kropka wpisy (+2)
  • może generować błędy, gdy katalogi są zagnieżdżone zbyt głęboko. Wstaw closedir($s);przed finałem }do naprawy (+13)
  • zakończy się niepowodzeniem, jeśli katalog zawiera pozycję bez nazwy, należy false!==przejść do warunku while, aby to naprawić (+8)

z glob, 182 bajty (prawdopodobnie 163 w przyszłości 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)."
";}
  • nie wyświetla ani nie rekursuje ukrytych plików / katalogów
  • 2oznacza GLOB_MARK, doda ukośnik do wszystkich nazw katalogów, podobnie jakls -F
  • przez preg_replaceucieka GLOB znaki specjalne
    Mógłbym nadużywane preg_quotedo tego (-19); ale to się nie powiedzie w systemach Windows, ponieważ ukośnik odwrotny jest tam separatorem katalogu.
  • php może wkrótce zawierać funkcję glob_quote , która pozwoli na taką samą grę w golfa preg_quotei działanie na wszystkich systemach.

z iteratorami, 183 bajtami
(cóż, nie tylko iteratorami: używałem domyślnie SplFileInfo::__toString()do gry w golfa $f->getBaseName()i $f->isDir()starych funkcji 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)?"/":"","
";}
  • końcowe ukośniki nie są wymagane
  • wyświetla i cyklicznie ukryte wpisy ( ls -a)
  • wstaw ,4096lub ,FilesystemIterator::SKIP_DOTSprzed, ),1aby pominąć kropki (+5) ( ls -A)
  • flaga 1oznaczaRecursiveIteratorIterator::SELF_FIRST

0

PowerShell, 147 bajtów

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

Człowieku, wydaje mi się, że PS powinien być w stanie zrobić coś w stylu odpowiedzi na bash, ale nie wymyślam niczego krótszego niż to, co tu mam.

Wyjaśnienie:

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 bajtów

Zmodyfikowano z tej odpowiedzi SO . To tabulatory wcięcia, a nie spacje. Dane wejściowe zostaną pobrane jak "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

Wypróbuj online - To całkiem interesujące, że mogę przeglądać katalog w Ideone ...

Ta sama długość:

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

Partia, 237 bajtów

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

Gdzie \ t oznacza dosłowny znak tabulacji. Ta wersja zawiera końcowe \s na katalogach, ale 41 bajtów można zapisać, jeśli nie są potrzebne.


końcowe `s 'nie są potrzebne
— tylko ASCII,

0

Perl, 89 bajtów

Jest to przydatne, gdy w podstawowej dystrybucji znajduje się moduł znajdujący. Moduł Perla :: File :: Find nie przegląda drzewa w kolejności alfabetycznej, ale specyfikacja o to nie prosiła.

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

Właściwy skrypt ma 76 bajtów, policzyłem 13 bajtów dla opcji wiersza poleceń.



0

Java 8, 205 bajtów

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

Jest to pełne przesłanie programu, które pobiera dane wejściowe z pierwszego argumentu wiersza poleceń (nie jest to wyraźnie dozwolone, ale jest wykonywane przez wiele innych) i wypisuje dane wyjściowe na standardowe wyjście.

Wypróbuj online (zwróć uwagę na inną nazwę interfejsu)

Nie golfił

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]), "");
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.