[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 — это атом.

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

Кстати, обычные термы могут начинаться с подчеркивание или нет? Если могут, то как отличать терм от переменной, по первой букве которая не-подчеркивание ?
Re[4]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 26.01.06 13:25
Оценка: 16 (1)
Здравствуйте, Arioch2, Вы писали:

А готовые библиотечные функции использовать что, уже некошерно ?

start()->
L1=filelib:fold_files(".","[a-zA-Z0-9_]*",true,fun(X,A)->[{X,filelib:file_size(X)}|A] end,[]),
[io:fwrite("~p~n",[X])||X<-L1],
ok.
выводит такое :

{"./server_root/logs/access_disk_log_8888.1",109709}
{"./server_root/logs/access_disk_log_8888.idx",18}
{"./server_root/logs/access_disk_log_8888.siz",13}
{"./server_root/logs/access_log_8888",109797}
{"./server_root/logs/error_disk_log_8888.1",101211}
{"./server_root/logs/error_disk_log_8888.idx",18}
{"./server_root/logs/error_disk_log_8888.siz",13}
{"./server_root/logs/error_log_8888",101227}
{"./server_root/ssl/ssl_client.pem",1266}
{"./server_root/ssl/ssl_server.pem",1266}

берет подкаталоги и т.д. и т.п.
Re[5]: [Erlang] Рекурсивный обход директорий
От: Arioch2  
Дата: 26.01.06 13:36
Оценка:
G>Здравствуйте, Arioch2, Вы писали:

Не правда, не я. А так — хорошо
Re[6]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 26.01.06 13:54
Оценка:
Здравствуйте, Arioch2, Вы писали:

A>Не правда, не я. А так — хорошо

Пардон, это был Mamut. Не туда взглянул
Re[5]: [Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 26.01.06 14:54
Оценка:
G>А готовые библиотечные функции использовать что, уже некошерно ?

start()->
    L1=filelib:fold_files(".","[a-zA-Z0-9_]*",true,fun(X,A)->[{X,filelib:file_size(X)}|A] end,[]),
    [io:fwrite("~p~n",[X])||X<-L1],
    ok.


А что делать с директориями и файлами, которые содержат Юникод в названиях?
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[6]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 26.01.06 15:03
Оценка:
Здравствуйте, Mamut, Вы писали:

M>А что делать с директориями и файлами, которые содержат Юникод в названиях?

А как такое может быть ?
По какими ОСями ?
Re[7]: [Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 26.01.06 15:48
Оценка:
M>>А что делать с директориями и файлами, которые содержат Юникод в названиях?
G>А как такое может быть ?
G>По какими ОСями ?

Под WinXP. Например, у меня сейчас валяется фильм, в названии файла которого — японские символы. Часть музыки на диске — с турецкими символами. Винда настроена под русскую локаль
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[7]: [Erlang] Рекурсивный обход директорий
От: Arioch2  
Дата: 27.01.06 06:16
Оценка:
M>>А что делать с директориями и файлами, которые содержат Юникод в названиях?
G>А как такое может быть ?
Запрещено? И зачем тогда Эраднгу Юникод ?

G>По какими ОСями ?

А под какими не может ?
Re[8]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 27.01.06 08:16
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Под WinXP. Например, у меня сейчас валяется фильм, в названии файла которого — японские символы. Часть музыки на диске — с турецкими символами. Винда настроена под русскую локаль


Насколько я знаю, Ерланг с юникодом не работает — так что, скорее всего, тут облом
Re[9]: [Erlang] Рекурсивный обход директорий
От: Arioch2  
Дата: 27.01.06 08:57
Оценка:
Здравствуйте, gandalfgrey, Вы писали:

G>Здравствуйте, Mamut, Вы писали:


M>>Под WinXP. Например, у меня сейчас валяется фильм, в названии файла которого — японские символы. Часть музыки на диске — с турецкими символами. Винда настроена под русскую локаль


G>Насколько я знаю, Ерланг с юникодом не работает — так что, скорее всего, тут облом


Вот это правда облом. У него же все строки юникодные !!!

Это вообще в его либаз отсутствует, или на конкретных платформаx ?
Re[10]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 27.01.06 09:27
Оценка:
Здравствуйте, Arioch2, Вы писали:

A>Вот это правда облом. У него же все строки юникодные !!!

A>Это вообще в его либаз отсутствует, или на конкретных платформаx ?
Все библиотечные функции работы со строками предполагают, что это ASCII-8. То-есть целое цисло < 256
есть какие-то либы (внешние) для юникода, но сам никогда не использовал
а вот интересно, dir показывает юникодные имена файлов ?
Re[11]: [Erlang] Рекурсивный обход директорий
От: Arioch2  
Дата: 27.01.06 09:47
Оценка:
G>Все библиотечные функции работы со строками предполагают, что это ASCII-8. То-есть целое цисло < 256

Вот это плохо.
Надо будет пристальнее к ejabberd присмотреться, он вероятно свои реализует функции ?

Не было обсуждений насчет юникода в ErLang'e ? ведь наверняка копья уже ломались, неизветсно с каким результатом.
Re[12]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 27.01.06 10:01
Оценка:
Здравствуйте, Arioch2, Вы писали:

A>Вот это плохо.

A>Надо будет пристальнее к ejabberd присмотреться, он вероятно свои реализует функции ?
A>Не было обсуждений насчет юникода в ErLang'e ? ведь наверняка копья уже ломались, неизветсно с каким результатом.
В мэйл-листе эту тему долго пережевывали, но ни к чему определенному не пришли
Есть либа SO WAP !, в ней поддержка юникода сделана
В принципе, стандартные функции переделать не сильно напряжно будет
хотя !
>string:len([0,65],[0,66],[0,67]]).
3
>string:chr([0,65],[0,66],[0,67]],[0,66]).
2
>string:tokens([0,65],[0,66],[0,67]],[0,66]]).
[[0,65]],[0,67]]]

работает для 16 битного !
о как !
но вот ввод-вывод по прежнему проблематичен
Re[12]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 27.01.06 10:13
Оценка:
Здравствуйте, Arioch2, Вы писали:

ВотЬ...
> io:fwrite("~n~s~n",[[0,65],[0,66],[0,67]]]).

^@A^@B^@C
ok
Как бы что-то похожее на правду ? Отдаленно, правда
и в консоли ничего вразумительного не увидеть...
Re[11]: [Erlang] Рекурсивный обход директорий
От: Mamut Швеция http://dmitriid.com
Дата: 27.01.06 10:20
Оценка:
A>>Вот это правда облом. У него же все строки юникодные !!!
A>>Это вообще в его либаз отсутствует, или на конкретных платформаx ?
G>Все библиотечные функции работы со строками предполагают, что это ASCII-8. То-есть целое цисло < 256
G>есть какие-то либы (внешние) для юникода, но сам никогда не использовал
G>а вот интересно, dir показывает юникодные имена файлов ?

Который финдовый? Нет

Explorer — без проблем. Большая часть программ под виндой испытывает проблемы с распознаванием таких файлов/директорий (даже MS Office таким грешит — не знаю, как в последней версии)
... << RSDN@Home 1.2.0 alpha rev. 619>>


dmitriid.comGitHubLinkedIn
Re[11]: [Erlang] Рекурсивный обход директорий
От: Трурль  
Дата: 27.01.06 13:07
Оценка:
Здравствуйте, gandalfgrey, Вы писали:


G>Все библиотечные функции работы со строками предполагают, что это ASCII-8. То-есть целое цисло < 256

Мне кажется, им пофиг 256.
> string:tokens("abc def a"++[1057,1058,1059,32,88]," ").
["abc","def",[97,1057,1058,1059],"X"]
Re[12]: [Erlang] Рекурсивный обход директорий
От: gandalfgrey  
Дата: 30.01.06 07:36
Оценка:
Здравствуйте, Трурль, Вы писали:

G>>Все библиотечные функции работы со строками предполагают, что это ASCII-8. То-есть целое цисло < 256

Т>Мне кажется, им пофиг 256.
Да, я уже заметил свою ошибку и уже даже написал о ней выше. Проблема остается со вводом-выводом — вот он не осуществляет никакого перекодирования. А используемые АПИшные функции — байтовые
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.