Ağaç ev dizinini görüntülemek için bir program yazın


9

C:/Stdin'den verilen veya bir dosyadan okunan bir dizin (örneğin ) verildiğinde, her dosya / klasör derinliğine göre girintili olarak bir dizin ağacı oluşturun.

Misal

Bir varsa C:/sadece iki klasör içeren sürücüyü foove barve barboş iken olduğu fooiçeren baz.txtgirişi ile daha sonra çalışan, C:/üretir:

C:/
    bar/
    foo/
        baz.txt

girdi ile çalışırken C:/foo/üretmek gerekir

foo/
    baz.txt

Bu kodgolf olduğundan, en düşük bayt sayısı kazanır. Dosya uzantıları (gibi baz.txt) isteğe bağlıdır. Ekstra notlar: gizli dosyalar yok sayılabilir, dizinler gerçekten var olmalıdır, dosyaların yazdırılamaz karakterler veya yeni satırlar içermediği varsayılabilir, ancak diğer tüm yazdırılabilir ASCII karakterleri iyidir (boşluklu dosya adları desteklenmelidir). Çıktı dosyaya veya stdout'a yazılabilir. Girintiler bir sekme karakteri veya 4 boşluktan oluşabilir.


1
Ek not: Bu soru kötü biçimlendirilmiş, bu nedenle yeniden biçimlendirme takdir edilecektir.
Mathime

Dosyalara erişimi olmayan diller otomatik olarak diskalifiye edilir mi?
Leaky Nun

Hangi dosya adları desteklenmelidir? Adlarında boşluk bulunan dosyalar? Yeni satırlarla mı? Yazdırılamayan karakterlerle mi? Gizli dosyalar (başlangıçtan itibaren .) ne olacak?
Kapı tokmağı

1
@LeakyNun Başvuru sorununun çıktısı bir dizi dizidir. Bu soru, stdout'a yazdırılmak üzere dizin ağacının bir temsilini gerektirir.
Mathime

1
Girdi bir işleve dize parametresi olabilir mi?
mbomb007

Yanıtlar:


10

bash, 61 58 54 bayt

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

Komut satırı bağımsız değişkeni olarak girdi alır, STDOUT'ta çıktı alır.

Sonuna yakın boşlukların |gaslında bir sekme karakteri olduğuna dikkat edin (SE, mesajları görüntülerken boşluklara dönüştürür).

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
'

@Dennis'e 4 bayt için teşekkürler !


2

Dyalog APL , 48 bayt

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

karakter girişi istemi

'dir/s/b ', metnin başına ekle

⎕SH kabukta yürütmek

r←saklayın r

karakter matrisinde dizeler listesi yapabilir

artan sıralama endeksleri

r[... ]yeniden sırala r [sıralı]

(... )shell komutunun standart dışında şunları yapın:

'[^\\]+\\'⎕R' ' regex, ters eğik çizgi olmayan ters eğik çizgi işlemlerini dört boşlukla değiştirir

1↓ ilk satırı bırak

⊂∘⊃, ilk önce ekli [satır]

Komut istemine "\ tmp" girilmesinin sonucu bilgisayarımda şu şekilde başlar:

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


Dizinlerde sonda \ karakteri olması gerekmez mi?
Neil


2

SML , 176 bayt

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)

%Bir dizeyi argüman olarak alan bir işlevi (diğerleri arasında) bildirir . Geçerli dizin için % "C:/Some/Path";veya ile arayın % (getDir());.

Ben FileSysbu meydan okuma okuduktan sonra keşfetti normalde işlevsel olarak kullanılan dil StandardML kim -Library kullanıyorum.

Özel karakterler !, &, $ve %dilin kendisi özel bir anlamı var ve sadece tanımlayıcı olarak kullanılır; ancak, başka türlü ihtiyaç duyulan bazı alanlardan kurtulmaya izin veren standart alfasayısal tanımlayıcılarla karıştırılamaz.

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

Bu şekilde SML / NJ veya Moscow ML * ile önek eklenerek derlenebilir load"OS";.

* Bkz mosml.org. 2'den fazla bağlantı yayınlayamazsınız.


1

C # (.NET Core) , 222 bayt

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

Çevrimiçi deneyin!


Sungolf:

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

İlk defa bir Mainişlevi tekrarladım !

C # üzerinde daha fazla bilgiye sahip bir kişinin daha fazla golf oynayabileceğine inanıyorum.


0

PHP, 180 bayt

  • ilk argüman: yolun sonunda eğik çizgi (veya ters eğik çizgi) olması gerekir
  • ikinci argüman: seviye varsayılan olarak NULLşu şekilde olur ve 0tarafından yorumlanır str_repeat; belirtilmezse bir uyarı gönderir

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
";}
  • görüntüler dosyaları ve dizinleri gizli ama -recurse gizli dizinleri gelmez
    parantez içine eklemek is_dir(...)?d(...):"..."çıkışı (2) gizli girdileri kaldırmak için
    değiştirin "#^\.#"ile#^\.+$# (+2) / ekrana gizli girdileri recurse ama girdileri nokta atlamak
  • dizinler çok derin yuvalanmışsa hata atabilir. Finalden closedir($s);önce ekle}Düzeltmek (+13)
  • bir dizin adsız bir girdi içeriyorsa başarısız olur, false!==düzeltmek için while koşulunun başına (+8)

glob ile, 182 bayt (muhtemelen php gelecekteki 163)

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)."
";}
  • gizli dosyaları / dizinleri görüntülemez veya geri almaz
  • 2 anlamına gelir GLOB_MARK , tüm dizin adlarına eğik çizgi eklerls -F
  • preg_replacekaçar özel karakterler topak
    ı istismar olabilirdipreg_quote (-19) bunun için; ancak ters eğik çizgi orada dizin ayırıcı olduğundan Windows sistemlerinde başarısız olur.
  • php olabilir yakında bir işlev içerir glob_quote aynı şekilde golf sağlayacak, preg_quotetüm sistemlerde ve iş.

yineleyicilerle, 183 bayt
(sadece yineleyiciler değil: SplFileInfo::__toString()golf $f->getBaseName()ve $f->isDir()eski PHP 4 işlevlerini örtük olarak kullandım .)

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)?"/":"","
";}
  • sondaki eğik çizgi gerekmez
  • gizli girişleri görüntüler ve tekrarlar ( ls -a)
  • insert ,4096veya ,FilesystemIterator::SKIP_DOTSöncesinde ),1((+5) girişlerini nokta atlamak için ls -A)
  • bayrak 1duruyorRecursiveIteratorIterator::SELF_FIRST

0

PowerShell, 147 bayt

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

Dostum, PS'nin bash cevabı gibi bir şey yapabilmesi gerektiğini hissediyorum, ama buraya geldiğimden daha kısa bir şey bulamıyorum.

Açıklama:

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 bayt

Dan Modifiye bu SO cevap . Bunlar girintiler için sekmelerdir, boşluklar değil. Girdi gibi alınacaktır "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

Online deneyin - Ideone dizinine göz atmak izin oldukça ilginç ...

Aynı uzunlukta:

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

Toplu, 237 bayt

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

Burada \ t değişmez sekme karakterini temsil eder. Bu sürüm \dizinlerdeki sonları içerir , ancak gerekli değilse 41 bayt kaydedilebilir.


sondaki `` `gerekli değil
sadece ASCII

0

Perl, 89 bayt

Çekirdek dağıtımda bir bulma modülü olduğunda kullanışlıdır. Perl's File :: Find modülü ağaçta alfabetik sırada geçiş yapmaz, ancak spec bunu istemedi.

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

Komut dosyası 76 bayt, komut satırı seçenekleri için 13 bayt saydım.



0

Java 8, 205 bayt

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

Bu, ilk komut satırı argümanından girdi alan (açıkça izin verilmez, ancak başkaları tarafından yapılır) ve çıktıyı standart çıktıya yazdıran tam bir program gönderimidir.

Çevrimiçi Deneyin (farklı arayüz adına dikkat edin)

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]), "");
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.