Escreva um programa para exibir a casa na árvore de diretórios


9

Dado um diretório (como C:/), fornecido pelo stdin ou lido de um arquivo, produza uma árvore de diretórios, com cada arquivo / pasta recuado com base em sua profundidade.

Exemplo

Se eu tiver um C:/carro que só contém duas pastas fooe bar, e baré ao mesmo tempo vazia foocontém baz.txt, em seguida, executando com a entrada C:/produz:

C:/
    bar/
    foo/
        baz.txt

durante a execução com entrada C:/foo/deve produzir

foo/
    baz.txt

Como este é um codegolf, a menor contagem de bytes vence. As extensões de arquivo (como baz.txt) são opcionais. Notas extras: os arquivos ocultos podem ser ignorados, os diretórios devem realmente existir, pode-se supor que os arquivos não contenham caracteres não imprimíveis ou novas linhas, mas todos os outros caracteres ASCII imprimíveis são adequados (nomes de arquivos com espaços devem ser suportados). A saída pode ser gravada em arquivo ou stdout. As indentações podem ser compostas por um caractere de tabulação ou quatro espaços.


11
Nota extra: esta questão está mal formatada, portanto uma reformatação seria apreciada.
— Mathime 16/07/2016

Os idiomas que não têm acesso aos arquivos são desqualificados automaticamente?
— Leaky Nun

Quais nomes de arquivos precisam ser suportados? Arquivos com espaços em seus nomes? Com novas linhas? Com caracteres não imprimíveis? E os arquivos ocultos (começando com .)?
— Maçaneta

11
@LeakyNun A saída da pergunta de referência é uma matriz de matrizes. Esta pergunta requer que uma representação da árvore de diretórios seja impressa no stdout.
— Mathime 16/07/2016

11
A entrada pode ser um parâmetro de string para uma função?
— Mbomb007

Respostas:


10

bash, 61 58 54 bytes

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

Recebe a entrada como argumento da linha de comando e sai em STDOUT.

Observe que os espaços próximos ao final antes da |gsão realmente um caractere de tabulação (o SE os converte em espaços ao exibir postagens).

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
'

Obrigado a @Dennis por 4 bytes!


2

Dyalog APL , 48 bytes

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

⍞ prompt para entrada de caracteres

'dir/s/b ', anexar texto

⎕SH executar em shell

r←armazenar em r

↑ faça a lista de strings na matriz de caracteres

⍋ índices para classificação crescente

r[... ]reordenar r [classificado]

(... )no comando padrão fora do shell, faça:

'[^\\]+\\'⎕R' ' regex substitui execuções terminadas por barra invertida por quatro espaços

1↓ largar a primeira linha

⊂∘⊃, preceda a primeira [linha] fechada

O resultado da inserção de "\ tmp" no prompt começa da seguinte maneira no meu computador:

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

⋮


Os diretórios não deveriam ter caracteres \ à direita?
— 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)

Declara (entre outras) uma função %que aceita uma string como argumento. Ligue com % "C:/Some/Path";ou % (getDir());para o diretório atual.

Estou usando a linguagem StandardML, normalmente bastante funcional, cuja FileSysbiblioteca-descobri depois de ler este desafio.

Os caracteres especiais !, &, $e %não têm nenhum significado especial em sua própria língua e são simplesmente usadas como identificadores; no entanto, eles não podem ser misturados com os identificadores alfanuméricos padrão, o que permite eliminar alguns espaços necessários.

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

Pode ser compilado assim com SML / NJ ou com Moscow ML * prefixando com load"OS";.

* Veja mosml.org, não é possível postar mais de 2 links.


1

C # (.NET Core) , 222 bytes

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

Experimente online!


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

Primeira vez em que recursionei uma Mainfunção!

Acredito que uma pessoa que tenha um conhecimento mais recente de C # possa jogar mais, porque eu não programava em C # há algum tempo!


0

PHP, 180 bytes

  • primeiro argumento: o caminho deve ter uma barra final (ou barra invertida)
  • segundo argumento: o nível padrão é NULLe será interpretado como 0por str_repeat; emitirá um aviso se não for fornecido

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
";}
  • exibe arquivos e diretórios ocultos, mas não recursa diretórios ocultos,
    adicione parênteses is_dir(...)?d(...):"..."para remover entradas ocultas da saída (+2)
    substitua "#^\.#"por #^\.+$#para exibir / recursar entradas ocultas, mas pule entradas de ponto (+2)
  • pode gerar erros quando os diretórios estão aninhados muito profundamente. Inserir closedir($s);antes da final }para corrigir (+13)
  • falhará se um diretório contiver uma entrada sem nome, preceda false!==a condição while para corrigir (+8)

com glob, 182 bytes (provavelmente 163 no php futuro)

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)."
";}
  • não exibe ou recursa arquivos / diretórios ocultos
  • 2 apoia GLOB_MARK , acrescentará uma barra a todos os nomes de diretório, assim comols -F
  • os preg_replacecaracteres especiais escapes glob que
    eu poderia ter abusado preg_quotepor isso (-19); mas isso falharia nos sistemas Windows, pois a barra invertida é o separador de diretórios lá.
  • O php pode incluir em breve uma função glob_quote , que permitirá o mesmo golfe preg_quotee o trabalho em todos os sistemas.

com iteradores, 183 bytes
(bem, não puramente iteradores: usei implícito SplFileInfo::__toString()no golfe $f->getBaseName()e $f->isDir()nas funções antigas do 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)?"/":"","
";}
  • nenhuma barra final necessária
  • exibe e recursa entradas ocultas ( ls -a)
  • inserir ,4096ou ,FilesystemIterator::SKIP_DOTSantes ),1para pular entradas de ponto (+5) ( ls -A)
  • flag 1significaRecursiveIteratorIterator::SELF_FIRST

0

PowerShell, 147 bytes

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

Cara, eu sinto que o PS deve ser capaz de fazer algo como a resposta do bash, mas não estou apresentando nada mais curto do que o que tenho aqui.

Explicação:

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 bytes

Modificado a partir desta resposta SO . Essas são guias para recuo, não espaços. Entrada será tomada como "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

Experimente online - é bem interessante que eu tenha permissão para navegar no diretório no Ideone ...

Mesmo comprimento:

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

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

Onde \ t representa o caractere de tabulação literal. Esta versão inclui os \s finais nos diretórios, mas 41 bytes podem ser salvos se não forem necessários.


os `\` s finais não são necessários
— somente ASCII

0

Perl, 89 bytes

É útil quando há um módulo de localização na distribuição principal. O módulo File :: Find do Perl não atravessa a árvore em ordem alfabética, mas a especificação não pediu isso.

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

O script propriamente dito é 76 bytes, contei 13 bytes para as opções de linha de comando.



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

Este é um envio completo do programa que recebe a entrada do seu primeiro argumento de linha de comando (não é explicitamente permitido, mas é feito por muitos outros) e imprime a saída na saída padrão.

Experimente Online (observe o nome da interface diferente)

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]), "");
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.