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


9

З огляду на каталог (такий як C:/), що видається з stdin або зчитується з файлу, створюють дерево каталогів, при цьому кожен файл / папка з відступом відбивається на основі його глибини.

Приклад

Якщо у мене є C:/диск , який містить тільки дві папки fooі bar, і barпорожньо в той час як fooмістить baz.txt, а потім працює з вхідним C:/виробляє:

C:/
    bar/
    foo/
        baz.txt

в той час як біг з введенням C:/foo/повинен виробляти

foo/
    baz.txt

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


1
Додаткова примітка: це питання неформатоване, тому було б вдячне переформатування.
Mathime

Мови, які не мають доступу до файлів, автоматично дискваліфікуються?
Leaky Nun

Які назви файлів потрібно підтримувати? Файли з пробілами в їх назвах? З новими рядками? З недрукованими символами? Що з прихованими файлами (починаючи з .)?
Дверна ручка

1
@LeakyNun Результатом опорного питання є масив масивів. Це запитання вимагає друкування дерева каталогів для друку в stdout.
Mathime

1
Чи може вхід бути рядковим параметром функції?
mbomb007

Відповіді:


10

bash, 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

Діалог APL , 48 байт

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

запит на введення символів

'dir/s/b ', подати текст

⎕SH виконати в оболонці

r←зберігати в р

скласти список рядків у матрицю символів

індекси для висхідного сортування

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 повинен бути в змозі зробити щось на зразок баш-відповіді, але я не придумую нічого коротшого, ніж те, що я тут маю.

Пояснення:

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

Змінено з цієї відповіді ТА . Це вкладки для відступу, а не пробіли. Введення буде прийнято як би "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's :: 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]),"");}}

Це повноцінне подання програми, яке бере вхід з першого аргументу командного рядка (не дозволено явно, але робиться багатьма іншими) і друкує вихід у стандартний режим.

Спробуйте в Інтернеті (зверніть увагу на іншу назву інтерфейсу)

Безумовно

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.