Напишите программу для отображения каталога Treehouse


9

Для данного каталога (например, C:/), полученного из stdin или считанного из файла, создайте дерево каталогов, в котором каждый файл / папка имеет отступ с учетом его глубины.

пример

Если у меня есть C:/диск, который содержит только две папки fooи bar, и barпустой, в то время как fooсодержит baz.txt, то запуск с вводом C:/производит:

C:/
    bar/
    foo/
        baz.txt

при работе с вводом C:/foo/следует выдавать

foo/
    baz.txt

Поскольку это Codegolf, выигрывает меньшее количество байтов. Расширения файлов (такие как baz.txt) не являются обязательными. Дополнительные примечания: скрытые файлы можно игнорировать, каталоги должны фактически существовать, можно предположить, что файлы не содержат непечатаемых символов или новых строк, но все остальные печатаемые символы ASCII хороши (имена файлов с пробелами должны поддерживаться). Вывод может быть записан в файл или стандартный вывод. Отступы могут состоять из символа табуляции или 4 пробелов.


1
Дополнительное примечание: этот вопрос плохо отформатирован, поэтому желательно переформатировать.
Матим

Языки, которые не имеют доступа к файлам, автоматически дисквалифицируются?
Утренняя монахиня

Какие имена файлов должны поддерживаться? Файлы с пробелами в их именах? С символами новой строки? С непечатными символами? Как насчет скрытых файлов (начиная с .)?
Дверная ручка

1
@LeakyNun Выход справочного вопроса - это массив массивов. Этот вопрос требует представления дерева каталогов для вывода на стандартный вывод.
Матим

1
Может ли ввод быть строковым параметром функции?
mbomb007

Ответы:


10

Баш, 61 58 54 байта

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

Принимает ввод в качестве аргумента командной строки, выводит на STDOUT.

Обратите внимание, что пробелы в конце перед |gсимволом табуляции фактически являются символом табуляции (SE преобразует их в пробелы при отображении сообщений).

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 за 4 байта!


2

Dyalog APL , 48 байтов

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

запрос на ввод символов

'dir/s/b ', предварять текст

⎕SH выполнить в оболочке

r←магазин в р

составить список строк в символьную матрицу

индексы для сортировки по возрастанию

r[... ]перезаказ г [отсортировано]

(... )по стандартной команде оболочки выполните:

'[^\\]+\\'⎕R' ' регулярное выражение заменяет завершенные с обратной косой чертой последовательности без обратной косой черты четырьмя пробелами

1↓ бросить первую строку

⊂∘⊃, добавьте в начало первую [строку]

Результат ввода "\ tmp" в подсказку начинается на моем компьютере следующим образом:

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


Разве в каталогах не должно быть конечных \ символов?
Нил


2

SML , 176 байт

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)

Объявляет (среди прочего) функцию, %которая принимает строку в качестве аргумента. Позвонить с % "C:/Some/Path";или % (getDir());для текущего каталога.

Я использую обычно довольно функционально используемый язык StandardML, FileSysбиблиотеку которого я обнаружил после прочтения этого задания.

Специальные символы !, &, $и %не имеют особого значения в самом языке и просто используются в качестве идентификаторов; однако их нельзя смешивать со стандартными буквенно-цифровыми идентификаторами, что позволяет избавиться от некоторых других необходимых мест.

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

Может быть скомпилирован так с SML / NJ или с московским ML * с префиксом load"OS";.

* Смотрите mosml.org, не можете опубликовать более 2 ссылок.


1

C # (.NET Core) , 222 байта

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

Попробуйте онлайн!


Негольф:

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

Впервые я когда-либо повторял Mainфункцию!

Я верю, что человек, который имеет более глубокие знания C #, может больше играть в гольф, так как я некоторое время не программировал на C #!


0

PHP, 180 байт

  • Первый аргумент: путь должен иметь косую черту (или обратную косую черту)
  • Второй аргумент: по умолчанию на уровне до NULLи будет интерпретироваться как 0путем str_repeat; выдаст предупреждение, если не указано

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
";}
  • отображает скрытые файлы и папки, но не рекурсией скрытых каталогов
    добавить в круглых скобки , is_dir(...)?d(...):"..."чтобы удалить скрытые записи с выхода (+2)
    заменить "#^\.#"с #^\.+$#на дисплей / рекурсии скрытых записей , но пропустить точку записи (+2)
  • может выдавать ошибки, если каталоги вложены слишком глубоко. Вставить closedir($s);перед финалом, }чтобы исправить (+13)
  • потерпит неудачу, если каталог содержит запись без имени, добавьте false!==условие while для исправления (+8)

с glob, 182 байта (вероятно, 163 в будущем 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)."
";}
  • не отображать и не просматривать скрытые файлы / каталоги
  • 2означает GLOB_MARK, добавит косую черту ко всем именам каталогов, как иls -F
  • preg_replaceускользает Глоб специальные символы
    Я мог бы злоупотребляли preg_quoteдля этого (-19); но это не сработает в системах Windows, так как обратная косая черта является разделителем каталогов.
  • Вскоре php может включать функцию glob_quote , которая позволит играть в гольф так же, как preg_quoteи работать на всех системах.

с итераторами, 183 байта
(ну, не чисто итераторы: я использовал неявное SplFileInfo::__toString()для гольфа $f->getBaseName()и $f->isDir()для старых функций 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)?"/":"","
";}
  • косая черта не требуется
  • отображает и повторяет скрытые записи ( ls -a)
  • вставить ,4096или ,FilesystemIterator::SKIP_DOTSперед ),1пропуском записей точек (+5) ( ls -A)
  • флаг 1обозначаетRecursiveIteratorIterator::SELF_FIRST

0

PowerShell, 147 байт

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

Чувак, я чувствую, что PS должен быть в состоянии сделать что-то вроде ответа bash, но я не придумаю ничего более короткого, чем то, что я получил здесь.

Объяснение:

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 байт

Изменено из этого SO ответа . Это вкладки для отступа, а не пробелы. Вход будет принят как "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

Попробуйте онлайн - довольно интересно, что мне разрешено просматривать каталог на Ideone ...

Одинаковая длина:

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

Пакет, 237 байт

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

Где \ t представляет буквенный символ табуляции. Эта версия включает в себя конечные \s для каталогов, но 41 байт может быть сохранен, если они не нужны.


завершающие `не нужны
только ASCII

0

Perl, 89 байт

Это полезно, когда в основном дистрибутиве есть модуль поиска. Модуль Perl File :: Find не пересекает дерево в алфавитном порядке, но спецификация не просила об этом.

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

Сценарий сам по себе составляет 76 байтов, для параметров командной строки я насчитал 13 байтов.



0

Java 8, 205 байт

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

Это полное представление программы, которое берет ввод из своего первого аргумента командной строки (явно не разрешено, но сделано многими другими) и выводит вывод в стандартный вывод.

Попробуйте онлайн (обратите внимание на другое имя интерфейса)

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]), "");
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.