Escribir un programa para mostrar la casa del árbol del directorio

9

Dado un directorio (como C:/), dado desde stdin o leído desde un archivo, produce un árbol de directorios, con cada archivo / carpeta sangrado en función de su profundidad.

Ejemplo

Si tengo un C:/coche que sólo contiene dos carpetas fooy bar, y bares, en vacío foocontiene baz.txt, a continuación, ejecutar con la entrada C:/produce:

C:/
    bar/
    foo/
        baz.txt

mientras se ejecuta con entrada C:/foo/debe producir

foo/
    baz.txt

Como se trata de codegolf, gana el conteo de bytes más bajo. Las extensiones de archivo (como baz.txt) son opcionales. Notas adicionales: los archivos ocultos pueden ignorarse, los directorios deben existir, se puede suponer que los archivos no contienen caracteres no imprimibles o nuevas líneas, pero todos los demás caracteres ASCII imprimibles están bien (los nombres de archivos con espacios deben ser compatibles). La salida se puede escribir en un archivo o stdout. Las hendiduras pueden estar formadas por un carácter de tabulación o 4 espacios.

Mathime
fuente
1
Nota adicional: esta pregunta está mal formateada, por lo que agradecería un reformateo.
Mathime
¿Se descalifican automáticamente los idiomas que no tienen acceso a los archivos?
Leaky Nun
¿Qué nombres de archivo deben ser compatibles? ¿Archivos con espacios en sus nombres? Con nuevas líneas? ¿Con caracteres no imprimibles? ¿Qué pasa con los archivos ocultos (comenzando con .)?
Pomo de la puerta
1
@LeakyNun La salida de la pregunta de referencia es una matriz de matrices. Esta pregunta requiere una representación del árbol de directorios que se imprimirá en stdout.
Mathime
1
¿Puede la entrada ser un parámetro de cadena para una función?
mbomb007

Respuestas:

10

bash, 61 58 54 bytes

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

Toma la entrada como un argumento de línea de comando, sale en STDOUT.

Tenga en cuenta que los espacios cerca del final antes del |gson en realidad un carácter de tabulación (SE los convierte en espacios cuando se muestran publicaciones).

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
'

¡Gracias a @Dennis por 4 bytes!

Pomo de la puerta
fuente
2

Dyalog APL , 48 bytes

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

solicitud de entrada de caracteres

'dir/s/b ', anteponer texto

⎕SH ejecutar en shell

r←almacenar en r

hacer una lista de cadenas en una matriz de caracteres

índices para clasificación ascendente

r[... ]reordenar r [ordenado]

(... )en el estándar fuera del comando de shell, haga:

'[^\\]+\\'⎕R' ' regex reemplaza ejecuciones terminadas con barra invertida de barras no invertidas por cuatro espacios

1↓ soltar la primera línea

⊂∘⊃, anteponer la primera [línea] adjunta

El resultado de ingresar "\ tmp" en el indicador comienza de la siguiente manera en mi computadora:

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

Adán
fuente
¿No se supone que los directorios tienen \ caracteres finales?
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 otros) una función %que toma una cadena como argumento. Llame con % "C:/Some/Path";o % (getDir());para el directorio actual.

Estoy usando el lenguaje StandardML, normalmente bastante funcional, cuya FileSysbiblioteca descubrí después de leer este desafío.

Los caracteres especiales !, &, $y %no tienen ningún significado especial en el lenguaje mismo y se utilizan simplemente como identificadores; sin embargo, no se pueden mezclar con los identificadores alfanuméricos estándar que permiten deshacerse de algunos espacios necesarios.

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

Puede compilarse así con SML / NJ o con Moscow ML * prefijando con load"OS";.

* Ver mosml.org, no puede publicar más de 2 enlaces.

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

Pruébalo en línea!


El 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 primera vez que recursé una Mainfunción!

¡Creo que una persona que tiene un conocimiento más reciente de C # puede jugar más golf, ya que no programé en C # por algún tiempo!

sergiol
fuente
0

PHP, 180 bytes

  • primer argumento: la ruta debe tener una barra inclinada final (o barra diagonal inversa)
  • segundo argumento: el nivel predeterminado es NULLy será interpretado como 0por str_repeat; lanzará una advertencia si no se proporciona

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
";}
  • muestra archivos y directorios ocultos, pero no repite directorios ocultos,
    agregue paréntesis is_dir(...)?d(...):"..."para eliminar las entradas ocultas de la salida (+2)
    reemplace "#^\.#"con #^\.+$#para mostrar / repetir entradas ocultas pero omita las entradas de puntos (+2)
  • puede arrojar errores cuando los directorios están anidados demasiado profundo. Insertar closedir($s);antes de la final }para arreglar (+13)
  • fallará si un directorio contiene una entrada sin nombre, anteponiendo false!==la condición while para arreglar (+8)

con glob, 182 bytes (probablemente 163 en 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)."
";}
  • no muestra ni repite archivos / directorios ocultos
  • 2significa GLOB_MARK, agregará una barra diagonal a todos los nombres de directorio, al igual quels -F
  • los preg_replacecaracteres especiales de escape se
    podrían haber abusado preg_quotede esto (-19); pero eso fallaría en los sistemas Windows, ya que la barra diagonal inversa es el separador de directorio allí.
  • php pronto puede incluir una función glob_quote , que permitirá el mismo golf preg_quotey funcionará en todos los sistemas.

con iteradores, 183 bytes
(bueno, no solo iteradores: solía estar implícito SplFileInfo::__toString()en el golf $f->getBaseName()y $f->isDir()en las antiguas funciones de 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)?"/":"","
";}
  • no se requiere barra inclinada
  • muestra y recurre entradas ocultas ( ls -a)
  • inserte ,4096o ,FilesystemIterator::SKIP_DOTSantes ),1para omitir entradas de puntos (+5) ( ls -A)
  • bandera 1significaRecursiveIteratorIterator::SELF_FIRST
Tito
fuente
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

Hombre, siento que PS debería poder hacer algo como la respuesta bash, pero no se me ocurre nada más corto que lo que tengo aquí.

Explicación:

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

Python 2, 138 bytes

Modificado de esta respuesta SO . Esas son pestañas para la sangría, no espacios. La entrada se tomará 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

Pruébelo en línea : es bastante interesante que se me permita navegar por el directorio de Ideone ...

Mismo largo:

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

Donde \ t representa el carácter de tabulación literal. Esta versión incluye \s finales en directorios, pero se pueden guardar 41 bytes si no son necesarios.

Neil
fuente
los `\` s finales no son necesarios
solo ASCII el
0

Perl, 89 bytes

Es útil cuando hay un módulo de búsqueda en la distribución principal. El módulo Archivo :: Buscar de Perl no atraviesa el árbol en orden alfabético, pero la especificación no lo solicitó.

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

La secuencia de comandos propiamente dicha es de 76 bytes, conté 13 bytes para las opciones de línea de comandos.

daniel
fuente
0

Tcl , 116 bytes

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

Pruébalo en línea!

sergiol
fuente
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 es un envío completo del programa que toma la entrada de su primer argumento de línea de comandos (no permitido explícitamente, pero hecho por muchos otros) e imprime la salida a la salida estándar.

Pruébelo en línea (observe el nombre de la interfaz diferente)

Sin golf

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
fuente