[Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 23.01.06 14:50
Оценка:
Только не смейтесь над убогим

Надо было мне тут совершить обход директорий и вытащить список как директорий, так и файлов — с размерами файлов.

Значит, наваял я вот такое. На названия не обращайте внимания, тяжелое наследие первых родов ежей против шерсти
-module(mamut_parse_dir).

-export([parse_dir/1]).


%% Вызываем, собственно, вот эту самую функцию
parse_dir(PathToDir) -> 
    case filelib:is_dir(PathToDir) of
        false -> {error, not_a_dir};
        true -> 
            {Dir, parse_dirs(get_dirs(PathToDir)), get_files(PathToDir)}.
    end.

parse_dirs([]) ->    
    [];
parse_dirs([H|T]) -> 
    [H, get_files(H)] ++ [parse_dirs(T)].

%% Берем список поддиректорий, стырено здесь: http://schemecookbook.org/Erlang/FileWalkDirectoryTree
get_dirs(Path) ->
    P = filename:join(Path, "*"),
    lists:filter(
        fun(X) -> filelib:is_dir(X) end, 
        filelib:wildcard(P)).

%% Берем список файлов, творчески обработанная функчия сверху
%% Возвращаю кортеж {имя_файла, размер_файла}
get_files(Path) ->
    P = filename:join(Path, "*"),
    lists:map(fun(X) -> {X, filelib:file_size(X)} end,
        lists:filter(
            fun(X) -> filelib:is_regular(X) end, 
            filelib:wildcard(P))).


В общем мне понравилось Но вопрос — а можно еще кратчее и красивше
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re: [Erlang] Рекурсивный обход директорий
От: Трурль  
Дата: 23.01.06 16:08
Оценка: 21 (1)
Здравствуйте, Mamut, Вы писали:

get_all(Path) ->
    {Dirs,Files}=lists:splitwith({filelib,is_dir},filelib:wildcard(filename:join(Path, "*"))),
    [Path|lists:map(fun(X)->{X, filelib:file_size(X)} end, Files)] ++ 
          lists:append(lists:map(fun(X)-> get_all(X) end,Dirs)).

а потом
  lists:splitwith(fun({_,_})->true ; (_)->false end, get_all(Path)).
Re: [Erlang] Ашыпка
От: Mamut Швеция http://dmitriid.com
Дата: 23.01.06 16:36
Оценка:
А кто рекурсировать-то будет?

parse_dirs([]) ->    
    [];
parse_dirs([H|T]) -> 
    [H, get_files(H)] ++ parse_dirs(get_dirs(H)) ++ [parse_dirs(T)].
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[2]: [Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 23.01.06 17:02
Оценка:


Одно но. Оно не работает. То есть работает не на всех директориях.

Например,
D:\MAMUT\LITERATURE
+---Gaiman, Neil
|       coraline.zip
|       
\---Kluev, Evghenii
        mej dvuh stul'ev.htm


Срабатывает нормально:
{[],
 ["D:/mamut/literature",
  "d:/mamut/literature/Gaiman, Neil",
  {"d:/mamut/literature/Gaiman, Neil/coraline.zip",467599},
  "d:/mamut/literature/Kluev, Evghenii",
  {"d:/mamut/literature/Kluev, Evghenii/mej dvuh stul'ev.htm",281435}]}


D:\DOWNLOADS
|   20050912hw.gif
|   7z423.exe
|   acdsee.exe
|   Alcohol120_trial_1_9_5_3105.exe
|   AMD.wmv
|   [еще много файлов]
|   
+---Flash
|       A_Cool_W-Darshan_-11130.zip
|       Fade_Bet-Adrian_H-10515.zip
|       Image_Sc-Masher-4657.zip
|       Mouse_Ro-Ergin_Z-11068.zip
|       Transiti-Armand_N-215.zip
|       
+---org.eclipse.cdt.sdk-3.0.1-win32.x86
|   \---eclipse
|       +---features
|       |   +---org.eclipse.cdt.sdk_3.0.1
|       |   |       eclipse_update_120.jpg
[еще много чего...]


не срабатывает:
{[],
 ["D:/downloads",
  {"d:/downloads/20050912hw.gif",1149913},
  {"d:/downloads/7z423.exe",1071555},
  {"d:/downloads/AMD.wmv",6115602},
    
    [скипнуто]
    
  {"d:/downloads/FFXI_Theme_Installer.exe",7559120},
  {"d:/downloads/FINAL.mpg",19205540},
  {"d:/downloads/Firefox Setup 1.5.exe",5225384},
  {"d:/downloads/Flash",0},
    
    [скипнуто]
    
  {"d:/downloads/org.eclipse.cdt.sdk-3.0.1-win32.x86",0},


Где-то буг
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re: [Erlang] Рекурсивный обход директорий
От: Gaperton http://gaperton.livejournal.com
Дата: 23.01.06 17:31
Оценка:
Здравствуйте, Mamut, Вы писали:

M>parse_dirs([]) ->

M> [];
M>parse_dirs([H|T]) ->
M> [H, get_files(H)] ++ [parse_dirs(T)].

странный формат. у тебя в списке чередуются директории и списки файлов. Нехорошо.
Возьми их в тупл, штоль.
Re[2]: [Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 23.01.06 17:52
Оценка:
M>>parse_dirs([]) ->
M>> [];
M>>parse_dirs([H|T]) ->
M>> [H, get_files(H)] ++ [parse_dirs(T)].

G>странный формат. у тебя в списке чередуются директории и списки файлов. Нехорошо.

G>Возьми их в тупл, штоль.

Ага, есть такое Это одна из итераций формата. В один момент были и туплы. Сейчас уже не помню, почему остановился на таком.


dmitriid.comGitHubLinkedIn
Re[2]: [Erlang] Рекурсивный обход директорий
От: Трурль  
Дата: 24.01.06 06:38
Оценка: 14 (1) :))
Здравствуйте, Трурль, Вы некрасиво нифига написали:

Вот так, пожалуй, покрасивше будет.
parse_dir(PathToDir) -> 
    case filelib:is_dir(PathToDir) of
        false -> {error, not_a_dir};
        true ->  Dirs=get_dirs(PathToDir),  {dir,Dirs, get_files(Dirs)}.
    end.

get_dirs(Path) ->
    [Path|lists:append([get_dirs(X)|| X <- filelib:wildcard(Path++"/*"),filelib:is_dir(X)])].

get_files(Dirs) ->
    [{Y,filelib:file_size(Y)}|| Y <- lists:append([filelib:wildcard(X++"/*")||X <- Dirs])].
Re[3]: [Erlang] Рекурсивный обход директорий
От: Трурль  
Дата: 24.01.06 06:50
Оценка:
Здравствуйте, Mamut, Вы писали:

M> Где-то буг

Странно, lists:splitwith не работает на таких списках, хотя map и filter отрабатывают нормально.
Re: [Erlang] Рекурсивный обход директорий
От: c-smile Канада http://terrainformatica.com
Дата: 24.01.06 07:36
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Надо было мне тут совершить обход директорий и вытащить список как директорий, так и файлов — с размерами файлов.


Для сравнения то же самое но на моем tiscript (вариант ECMAScript)

function xdir( path )
{
  function foreach(n, func)
  {
    func(n); // вызываем func для каждого node файловой системы.
    if( n.isdir ) 
      for(var sn in n.nodes) foreach( sn, func );
  }
  foreach( new FileSystem.Node(path), 
           function(n) { stdout.printf("%s,%d\n",n.path, n.size); } );
}
// поехали!
xdir("/");


В принципе по всем половым признакам ECMAScript (JavaScript) это ФЯ.
Re[2]: [Erlang] Рекурсивный обход директорий
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 24.01.06 08:03
Оценка:
c-smile,

CS>Для сравнения то же самое но на моем tiscript (вариант ECMAScript)


CS>
CS>function xdir( path )
CS>{
CS>  function foreach(n, func)
CS>  {
CS>    func(n); // вызываем func для каждого node файловой системы.
CS>    if( n.isdir ) 
CS>      for(var sn in n.nodes) foreach( sn, func );
CS>  }
CS>  foreach( new FileSystem.Node(path), 
CS>           function(n) { stdout.printf("%s,%d\n",n.path, n.size); } );
CS>}
CS>// поехали!
CS>xdir("/");
CS>


CS>В принципе по всем половым признакам ECMAScript (JavaScript) это ФЯ.


Только "грязный" — куча побочных эффектов. Плюс:
Что возвращяет функция foreach?
Что возвращает функция xdir?

Лямбды — это уже интересно
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: [Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 24.01.06 08:20
Оценка:
get_files(Dirs) ->
    [{Y,filelib:file_size(Y)}|| Y <- lists:append([filelib:wildcard(X++"/*")||X <- Dirs])].


Это захватит и директории тоже. Вдобавок список получается не очень хорошим — сначала идут все абсолютно директории и поддиректории, а потмо все файлы во всех поддиректориях
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[2]: [Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 24.01.06 08:21
Оценка:
CS>Для сравнения то же самое но на моем tiscript (вариант ECMAScript)

function xdir( path )
{
  function foreach(n, func)
  {
    func(n); // вызываем func для каждого node файловой системы.
        // а что за func и откуда берется? :)
    if( n.isdir ) 
      for(var sn in n.nodes) foreach( sn, func );
  }
  foreach( new FileSystem.Node(path), 
           function(n) { stdout.printf("%s,%d\n",n.path, n.size); } );
}
// поехали!
xdir("/");


CS>В принципе по всем половым признакам ECMAScript (JavaScript) это ФЯ.
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[3]: [Erlang] Рекурсивный обход директорий
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 24.01.06 08:40
Оценка:
Mamut,

M> // а что за func и откуда берется?


Это параметр. Возможно тебя ввела в заблуждение расцветка. foreach — это просто имя функции, а не ключевое слово.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: [Erlang] Рекурсивный обход директорий
От: Arioch2  
Дата: 24.01.06 08:40
Оценка:
M> function foreach(n, func)
M> {
M> func(n); // вызываем func для каждого node файловой системы.
M> // а что за func и откуда берется?

Передается как параметр в функцию.

Собственно говоря, чем это отличается от Delphi.Net?
(в Delphi/Win32 и Turbo Pascal нет встроенныx итераторов, конструкция типа Visual Vasic'овского for each VAR in COLLECTION do )

анонимными функциями (да и то не уверен насчет Delphi для грядущего повсеместно .Net 2) ?

Честно говоря по-моему обычный императивный код по сути.
Re[4]: [Erlang] Рекурсивный обход директорий
От: Трурль  
Дата: 24.01.06 09:32
Оценка:
Здравствуйте, Mamut, Вы писали:

M>
M>get_files(Dirs) ->
M>    [{Y,filelib:file_size(Y)}|| Y <- lists:append([filelib:wildcard(X++"/*")||X <- Dirs])].
M>


M>Это захватит и директории тоже. Вдобавок список получается не очень хорошим — сначала идут все абсолютно директории и поддиректории, а потмо все файлы во всех поддиректориях

Отфильтровать забыл.

get_files(Dirs) ->
   [{Y,filelib:file_size(Y)}|| Y <- lists:append([filelib:wildcard(X++"/*")||X <- Dirs]),not filelib:is_dir(Y)].
Re: [Erlang] Ага, еще буги
От: Mamut Швеция http://dmitriid.com
Дата: 24.01.06 10:16
Оценка:
M>В общем мне понравилось Но вопрос — а можно еще кратчее и красивше

В общем, мне не понравилось Не обрабатываются директории, содержащие Юникод. Видать что-то где-то надо править ручками.... Ну да ладно, мне пока и этого хватает
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[3]: [Erlang] Рекурсивный обход директорий
От: c-smile Канада http://terrainformatica.com
Дата: 24.01.06 17:17
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

CS>>В принципе по всем половым признакам ECMAScript (JavaScript) это ФЯ.


LCR>Только "грязный" — куча побочных эффектов. Плюс:


Что имеется ввиду? Какие побочные эффекты?

LCR>Что возвращяет функция foreach?


все функции чег-то возвращают. Если явно не задано то
в стандарте определено что возвращается undefined value в этом случае.

LCR>Что возвращает функция xdir?


undefined.

LCR>Лямбды — это уже интересно


А вот кстати есть ли где определение ФЯ как классов?
Что должен иметь язык чтобы он считался ФЯ?

И как насчет proptotype based inheritance?
Re: [Erlang] Рекурсивный обход директорий
От: Arioch2  
Дата: 25.01.06 08:59
Оценка:
M> lists:filter(
M> fun(X) -> filelib:is_dir(X) end,
M> filelib:wildcard(P)).

А зачем тут анонимную функцию объявлять ?
Нельзя разве напрямую передать is_dir ?

К осожалению, насколько понял, синтаксис первый вариант не пропустит (а почему? не умеет, или есть принципиальные возражения?), но второй должен работать.

    lists:filter(
        filelib:is_dir, 
        filelib:wildcard(P)).


    lists:filter(
        {filelib,is_dir}, 
        filelib:wildcard(P)).
Re[2]: [Erlang] Рекурсивный обход директорий
От: Трурль  
Дата: 26.01.06 08:51
Оценка:
Здравствуйте, Arioch2, Вы писали:

A>К осожалению, насколько понял, синтаксис первый вариант не пропустит (а почему? не умеет, или есть принципиальные возражения?)


A>
A&gt;    lists:filter(
A&gt;        filelib:is_dir, 
A&gt;        filelib:wildcard(P)).
A&gt;

Потому что filelib:is_dir — это атом.
Re[3]: [Erlang] Рекурсивный обход директорий
От: Arioch2  
Дата: 26.01.06 10:21
Оценка:
Т>Потому что filelib:is_dir — это атом.

Это с двоеточием-то ? И все равно могли какой-нибудь синтаксис придумтаь про красивше и попонятнее

Кстати, обычные термы могут начинаться с подчеркивание или нет? Если могут, то как отличать терм от переменной, по первой букве которая не-подчеркивание ?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.