Tulis program untuk menampilkan treehouse direktori

9

Diberikan direktori (seperti C:/), diberikan dari stdin atau baca dari file, menghasilkan pohon direktori, dengan setiap file / folder diindentasi berdasarkan kedalamannya.

Contoh

Jika saya memiliki C:/drive yang hanya berisi dua folder foodan bar, dan barkosong saat fooberisi baz.txt, kemudian berjalan dengan input C:/menghasilkan:

C:/
    bar/
    foo/
        baz.txt

saat berjalan dengan input C:/foo/harus menghasilkan

foo/
    baz.txt

Karena ini adalah codegolf, jumlah byte terendah menang. Ekstensi file (seperti baz.txt) adalah opsional. Catatan tambahan: file tersembunyi dapat diabaikan, direktori harus benar-benar ada, dapat diasumsikan bahwa file tidak mengandung karakter yang tidak patut atau baris baru tetapi semua karakter ASCII yang dapat dicetak baik-baik saja (nama file dengan spasi harus didukung). Output dapat ditulis ke file atau stdout. Lekukan dapat terdiri dari karakter tab atau 4 spasi.

Mathime
sumber
1
Catatan tambahan: pertanyaan ini tidak diformat dengan baik, sehingga pemformatan ulang akan dihargai.
Mathime
Apakah bahasa yang tidak memiliki akses ke file didiskualifikasi secara otomatis?
Leaky Nun
Nama file apa yang harus didukung? File dengan spasi di namanya? Dengan baris baru? Dengan karakter yang tidak patut dicetak? Bagaimana dengan file tersembunyi (dimulai dengan .)?
Gagang pintu
1
@LeakyNun Keluaran pertanyaan referensi adalah array array. Pertanyaan ini membutuhkan representasi dari pohon direktori yang akan dicetak ke stdout.
Mathime
1
Bisakah input menjadi parameter string ke suatu fungsi?
mbomb007

Jawaban:

10

bash, 61 58 54 byte

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

Mengambil input sebagai argumen baris perintah, menghasilkan pada STDOUT.

Perhatikan bahwa spasi di dekat akhir sebelum |gsebenarnya adalah karakter tab (SE mengonversinya menjadi spasi saat menampilkan tulisan).

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
'

Berkat @ Dennis untuk 4 byte!

Gagang pintu
sumber
2

Dyalog APL , 48 byte

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

meminta input karakter

'dir/s/b ', teks depan

⎕SH jalankan di shell

r←simpan di r

membuat daftar string ke dalam matriks karakter

indeks untuk penyortiran naik

r[... ]menyusun ulang r [diurutkan]

(... )pada standar dari perintah shell, lakukan:

'[^\\]+\\'⎕R' ' regex menggantikan backslash yang diakhiri dengan non-backslash sebanyak empat spasi

1↓ turunkan baris pertama

⊂∘⊃, tambahkan dulu [baris] pertama terlampir

Hasil memasukkan "\ tmp" ke prompt dimulai sebagai berikut di komputer saya:

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

Adm
sumber
Bukankah direktori seharusnya memiliki karakter \ trailing?
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)

Menyatakan (antara lain) fungsi %yang menggunakan string sebagai argumen. Panggil dengan % "C:/Some/Path";atau % (getDir());untuk direktori saat ini.

Saya menggunakan bahasa StandardML yang biasanya digunakan secara fungsional yang FileSys-Library yang saya temukan setelah membaca tantangan ini.

Karakter khusus !, &, $dan %tidak memiliki arti khusus dalam bahasa itu sendiri dan hanya digunakan sebagai pengidentifikasi; Namun mereka tidak dapat dicampur dengan pengidentifikasi alfanumerik standar yang memungkinkan untuk menghilangkan beberapa ruang yang diperlukan.

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

Dapat dikompilasi seperti ini dengan SML / NJ atau dengan Moscow ML * dengan awalan dengan load"OS";.

* Lihat mosml.org, tidak dapat memposting lebih dari 2 tautan.

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

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

Pertama kali saya pernah mengulang suatu Mainfungsi!

Saya percaya seseorang yang memiliki pengetahuan C # yang lebih segar dapat golf lebih banyak, karena saya tidak memprogram C # untuk beberapa waktu!

sergiol
sumber
0

PHP, 180 byte

  • Argumen pertama: path harus memiliki garis miring (atau garis miring terbalik)
  • argumen kedua: level default ke NULLdan akan ditafsirkan sebagai 0oleh str_repeat; akan memberikan peringatan jika tidak disediakan

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
";}
  • menampilkan file dan direktori tersembunyi, tetapi tidak mengulang direktori tersembunyi
    menambahkan tanda kurung di sekitar is_dir(...)?d(...):"..."untuk menghapus entri tersembunyi dari output (+2)
    ganti "#^\.#"dengan #^\.+$#untuk menampilkan / rekur entri tersembunyi tetapi lewati entri titik (+2)
  • dapat melempar kesalahan saat direktori disarangkan terlalu dalam. Masukkan closedir($s);sebelum final }untuk memperbaikinya (+13)
  • akan gagal jika direktori berisi entri tanpa nama, false!==tergantung pada kondisi sementara untuk diperbaiki (+8)

dengan glob, 182 byte (mungkin 163 di php masa depan)

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)."
";}
  • tidak menampilkan atau mengulang file / direktori tersembunyi
  • 2singkatan GLOB_MARK, akan menambahkan garis miring ke semua nama direktori, seperti halnyals -F
  • yang preg_replacelolos gumpal karakter khusus
    saya bisa disalahgunakan preg_quoteuntuk ini (-19); tapi itu akan gagal pada sistem Windows, karena backslash adalah pemisah direktori di sana.
  • php dapat segera menyertakan fungsi glob_quote , yang akan memungkinkan bermain golf yang sama dengan preg_quotedan bekerja pada semua sistem.

dengan iterators, 183 byte
(well, bukan iterators murni: saya menggunakan implisit SplFileInfo::__toString()untuk golf $f->getBaseName()dan $f->isDir()ke fungsi PHP 4 lama).

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)?"/":"","
";}
  • tidak diperlukan garis miring garis miring
  • menampilkan dan berulang entri tersembunyi ( ls -a)
  • masukkan ,4096atau ,FilesystemIterator::SKIP_DOTSsebelum ),1untuk melewati entri titik (+5) ( ls -A)
  • bendera 1adalah singkatanRecursiveIteratorIterator::SELF_FIRST
Titus
sumber
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

Sobat, saya merasa seperti PS harus bisa melakukan sesuatu seperti jawaban bash, tapi saya tidak datang dengan sesuatu yang lebih pendek dari apa yang saya dapatkan di sini.

Penjelasan:

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
sumber
0

Python 2, 138 byte

Dimodifikasi dari jawaban SO ini . Itu adalah tab untuk indentasi, bukan spasi. Input akan diambil seperti "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

Cobalah online - Cukup menarik bahwa saya diizinkan menjelajahi direktori di Ideone ...

Sama panjang:

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
sumber
0

Batch, 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%

Di mana \ t mewakili karakter tab literal. Versi ini menyertakan trailing \s pada direktori tetapi 41 byte dapat disimpan jika tidak diperlukan.

Neil
sumber
trailing `s` tidak diperlukan
ASCII
0

Perl, 89 byte

Ini berguna ketika ada modul find di distribusi inti. File Perl :: Find module tidak melintasi susunan pohon dalam urutan abjad, tetapi spec tidak menanyakannya.

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

Skrip yang tepat adalah 76 byte, saya menghitung 13 byte untuk opsi baris perintah.

daniel
sumber
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

Cobalah online!

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

Ini adalah pengajuan program penuh yang mengambil input dari argumen baris perintah pertama (tidak diizinkan secara eksplisit, tetapi dilakukan oleh banyak orang lain) dan mencetak output ke standar keluar.

Cobalah Online (catat nama antarmuka yang berbeda)

Tidak disatukan

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
sumber