28
29:- module(dirtree,
30 [dirtree/2, 31 dirtree/3, 32 sortree/2, 33 sortree/3, 34 compare_by_attr/4, 35 extension_embedding_enable/0,
36 extension_to_embed/1, 37 source_target/2, 38 extensions_from_saved/1, 39 counted_extensions/1, 40 get_ftp_ls_output/2, 41 get_ftp_ls_output//1, 42 dirzap/1, 43 capture_attrs/3, 44 assign_path/2
45 ]). 46
47:- use_module([library(lambda),
48 library(dcg/basics),
49 library(aggregate),
50 library(xpath)
51 ]).
65:- dynamic extension_to_embed/1. 66:- dynamic source_target/2.
73dirtree(P, T) :-
74 dirtree(P, P, T).
75
76dirtree(P, Dir, element(dir, [name = Dir, size = S, path = P], D)) :-
77 exists_directory(P),
78 !,
79 scandir(P, Dir, D),
80 aggregate_all(sum(X),
81 (member(element(_, As, _), D),
82 memberchk(size = X, As)
83 ), S).
84dirtree(P, File, element(file, A, Q)) :-
85 ( catch((exists_file(P), size_file(P, S)), E, (print_message(error, E), S = 0))
86 -> A = [name = File, size = S, path = P],
87 embed(P, Q)
88 ; A = [name = File, size = 0, path = P]
89 ).
90
91scandir(P, _Dir, D) :-
92 directory_files(P, L),
93 findall(X, ( member(E, L), E \== '..', E \== '.',
94 format(atom(Q), '~w/~w', [P, E]),
95 dirtree(Q, E, X)), D).
102sortree(T, S) :-
103 sortree(compare_by_attr(name), T, S).
104
105:- meta_predicate sortree(3, +, -). 106
107sortree(C, element(E, As, Cs), element(E, As, Ss)) :-
108 predsort(C, Cs, Ts),
109 maplist(sortree, Ts, Ss).
110sortree(_C, E, E).
111
112compare_by_attr(A, R, X, Y) :-
113 xpath(X, /self(@A), Vx), xpath(Y, /self(@A), Vy), ( Vx @< Vy -> R = < ; R = > ).
121extension_embedding_enable :-
122 maplist(\E^( extension_to_embed(E)
123 -> true
124 ; assert(extension_to_embed(E))), [pl, php, tpl]).
125
126embed(P, XLines) :-
127 file_name_extension(_, X, P),
128 extension_to_embed(X),
129 setup_call_cleanup(open(P, read, H), fetch_lines(H, Lines), close(H)),
130 maplist(\Line^XLine^(XLine = element(line, [text = Line], [])), Lines, XLines),
131 !.
132embed(_, []).
133
134fetch_lines(H, L) :-
135 read_line_to_codes(H, Codes),
136 ( Codes == end_of_file ->
137 L = []
138 ;
139 atom_codes(A, Codes),
140 xml_quote_attribute(A, Q),
141 fetch_lines(H, T),
142 L = [Q|T]
143 ).
149extensions_from_saved(Exts) :-
150 source_target(_, XML),
151 load_xml_file(XML, DOM),
152 extensions_from_DOM(DOM, Exts).
153
154extensions_from_DOM(DOM, Exts) :-
155 aggregate_all(set(X), (xpath(DOM, //file(@name), File),
156 file_name_extension(_, X, File)
157 ), Exts).
158
159%% counted_extensions(Counted) is det.
160%
161% get all extensions and count each file
162%
163counted_extensions(Counted) :-
164 source_target(_, XML),
165 load_xml_file(XML, DOM),
166 setof(X = Count, (findall(Ext, (
167 xpath(DOM, //file(@name), File),
168 file_name_extension(_, Ext, File)), Exts),
169 aggregate(count, member(X, Exts), Count)
170 ), Counted).
171
172counted_extensions_old(Counted) :-
173 source_target(_, XML),
174 load_xml_file(XML, DOM),
175 extensions_from_DOM(DOM, ExtS),
176 maplist(\Ext^Count^(aggregate_all(count,
177 (xpath(DOM, //file(@name), File), file_name_extension(_, Ext, File) ), C), Count = (Ext = C) ), ExtS, Counted).
186get_ftp_ls_output(Stdout, Ftped) :-
187 phrase_from_file(get_ftp_ls_output(Ftped), Stdout).
188
189eos([],[]).
190get_ftp_ls_output([]) --> eos.
191get_ftp_ls_output([E|Es]) -->
192 ftp_ls_entry(E),
193 get_ftp_ls_output(Es).
194ftp_ls_entry(E) -->
195 "d",
196 entry(dir, E).
197ftp_ls_entry(E) -->
198 "-",
199 entry(file, E).
200
201s --> " ", whites.
202
203permission([R, W, X]) -->
204 [R, W, X].
205
206entry(Kind, element(Kind, [name = Name, size = Size, lastmod = T, user = User, group = Group, perm = P, c2 = I1], [])) -->
207 permission(UserP),
208 permission(GroupP),
209 permission(OthersP),
210 s,
211 integer(I1),
212 s,
213 string(GroupC),
214 s,
215 string(UserC),
216 s,
217 integer(Size),
218 timestamp(T),
219 string(NameC), "\n",
220 { maplist(atom_codes, P, [UserP, GroupP, OthersP]),
221 maplist(atom_codes, [User, Name, Group], [UserC, NameC, GroupC])
222 }.
223
224month(M, I) :-
225 atom_codes(A, M),
226 downcase_atom(A, D),
227 nth1(I, [jan,feb,mar,apr,maj,jun,jul,aug,sep,oct,nov,dec], D)
228 -> true
229 ; I = 0.
230
231timestamp(date(YYYY,MO,DD,HH,MM,SS,0,-,-)) -->
232 ( " ", [M,O,N], " ", [D1,D2], " ", [H1,H2], ":", [M1,M2], " "
233 -> {maplist(number_codes, [DD,HH,MM], [[D1,D2], [H1,H2], [M1,M2]]), month([M,O,N], MO), YYYY=2012, SS=0}
234 ; " ", [M,O,N], " ", [D1,D2], " ", [H1,H2,H3,H4], " " ->
235 {maplist(number_codes, [DD,YYYY], [[D1,D2], [H1,H2,H3,H4]]), month([M,O,N], MO), HH=0, MM=0, SS=0}
236 ).
237
238
239%% dirzap(+X:atom) is det.
240%
241% remove directory (content is lost of course)
242%
243dirzap(X) :-
244 dirtree(X, T),
245 forall(xpath(T, //file(@path), Path), delete_file(Path)), findall(Path, xpath(T, //dir(@path), Path), Dirs), reverse(Dirs, RDirs), maplist(delete_directory, RDirs).
255capture_attrs(Attr, element(_, Attrs, Tree), [Value|List]) :-
256 memberchk(Attr = Value, Attrs),
257 maplist(capture_attrs(Attr), Tree, SList),
258 flatten(SList, List).
264assign_path(element(dir, A, NoPath), element(dir, A, WithPath)) :-
265 memberchk(path=Path, A),
266 maplist(assign_path(Path), NoPath, WithPath).
267
268assign_path(Path, element(T, A, S), element(T, Wp, Sp)) :-
269 memberchk(name=N, A),
270 append(A, [path=Path], Wp),
271 atomic_list_concat([Path, N], /, Next),
272 ( T == dir
273 -> maplist(assign_path(Next), S, Sp)
274 ; Sp = S
275 )
Filesystem listing to XML.
This library provides utilities to load directories content from filesystem to XML element/3 and some utility. It's also possible load text of selected files types (by extension).
Of interest could be the parsing of FTP command 'ls', allowing remote browsing after
process_create
with redirection of standard output.*/