74%macro mp_dirlist(path=%sysfunc(pathname(work))
76 , outds=work.mp_dirlist
83%let getattrs=%upcase(&getattrs)XX;
84%let showparent=%upcase(&showparent)XX;
88%
if "%upcase(&sysscp)"=
"WIN" or
"%upcase(&sysscp)"=
"DNTHOST" %then %let mpsep=\;
91%local lvl nfront total room done mp_roots mpsep;
95%
if &fref ne 0 %then %let path=%sysfunc(pathname(&fref));
98%
if %length(&maxdepth)=0 or %sysfunc(verify(&maxdepth,0123456789))>0 %then %
do;
99 %
if "%upcase(&maxdepth)"=
"MAX" %then %let maxdepth=2147483647;
100 %
else %let maxdepth=0;
102%
if %length(&maxobs)=0 or %sysfunc(verify(&maxobs,0123456789))>0 %then %let maxobs=0;
105%mp_dropmembers(%scan(&outds,-1,.), libref=WORK)
109 length directory filepath $2000 file_or_folder $6 filename $255 ext $20
111 call missing(of _all_);
116%let fref1=%mf_getuniquefileref();
117%let fref2=%mf_getuniquefileref();
120%
if %length(&path)=0 %then %let mp_roots=1;
122%
if &mp_roots=1 %then %
do;
127 data work.__mp_dirlist_level;
128 length directory filepath $2000 file_or_folder $6 filename $255
129 ext $20 msg $200 level 8;
130 length drive $3 letters $26;
131 call missing(of _all_);
132 %
if "%upcase(&sysscp)"=
"WIN" or
"%upcase(&sysscp)"=
"DNTHOST" %then %
do;
133 letters=
'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
135 drive=cats(substr(letters,i,1),
':');
136 rc=filename(
"&fref1",cats(drive,
'\'));
141 filepath=cats(drive,
'\');
143 file_or_folder=
'folder';
147 rc=filename(
"&fref1");
154 file_or_folder=
'folder';
158 keep directory filepath file_or_folder filename ext msg level;
160 proc append base=&outds data=work.__mp_dirlist_level nowarn force;
163 data work.__mp_dirlist_frontier;
164 set work.__mp_dirlist_level(where=(file_or_folder=
'folder'));
173 data work.__mp_dirlist_frontier;
174 length filepath $2000 level 8;
175 filepath=symget(
'path');
181%let nfront=%sysfunc(coalesce(%mf_nobs(work.__mp_dirlist_frontier),0));
184%
do %until(&nfront=0 or &lvl>&maxdepth or &done=1);
186 data work.__mp_dirlist_level;
187 set work.__mp_dirlist_frontier;
188 length directory filepath $2000 file_or_folder $6 filename $255 ext $20
189 msg $200 sep $1 prefix $2000 fname $255 dmsg $200;
190 drop sep prefix fname dmsg rc did mid i;
196 rc=filename(
"&fref1", directory);
206 do while(length(directory)>1);
207 if substr(directory,length(directory),1) not in (
'/',
'\') then leave;
208 if length(directory)=3 and substr(directory,2,1)=
':' then leave;
209 directory=substr(directory,1,length(directory)-1);
212 if directory=
'/' or (length(directory)=3 and substr(directory,2,1)=
':')
213 then prefix=directory;
214 else prefix=cats(directory,sep);
218 filepath=cats(prefix,fname);
224 rc=filename(
"&fref2",filepath);
227 file_or_folder='folder';
232 if index(dmsg,'is not a directory')>0 then do;
233 file_or_folder='file';
234 ext=prxchange('s/.*\.{1,1}(.*)/$1/
',1,filename);
235 if filename=ext then ext=' ';
237 else if index(dmsg,'uthorization
')>0 then do;
238 /* present but not readable. It stays a file, as it was before the
239 entry test was fixed - the copy, hash and zip tools skip anything
240 that is not a file, and a backup that silently omits an unreadable
241 file is worse than one that fails on it */
242 file_or_folder='file
';
243 ext=prxchange('s/.*\.{1,1}(.*)/$1/
',1,filename);
244 if filename=ext then ext=' ';
248 /* listed but not openable at all - a broken link, for instance */
249 file_or_folder='locked
';
253 rc=filename("&fref2");
258 rc=filename("&fref1");
261 /* trim the level to what is left of the maxobs budget before appending */
262 %let total=%sysfunc(coalesce(%mf_nobs(&outds),0));
263 %let room=2147483647;
264 %if &maxobs>0 %then %let room=%eval(&maxobs-&total);
265 %if &room>0 %then %do;
266 data work.__mp_dirlist_level;
267 set work.__mp_dirlist_level(obs=&room);
269 proc append base=&outds data=work.__mp_dirlist_level force nowarn;
273 %let total=%sysfunc(coalesce(%mf_nobs(&outds),0));
274 %if &maxobs>0 and &total>=&maxobs %then %let done=1;
276 /* the folders of this level become the parents of the next one */
278 %if &done=0 and &lvl<&maxdepth %then %do;
279 data work.__mp_dirlist_frontier;
280 set work.__mp_dirlist_level(where=(file_or_folder='folder
'));
284 %let nfront=%sysfunc(coalesce(%mf_nobs(work.__mp_dirlist_frontier),0));
287 %let lvl=%eval(&lvl+1);
291/* include the starting folder itself, when asked */
292%if %substr(&showparent,1,1)=Y %then %do;
293 data work.__mp_dirlist_level;
294 length directory filepath $2000 file_or_folder $6 filename $255 ext $20
296 /* the parent is only listed when it can be opened, so a path that does
297 not exist stays an empty result even with showparent=YES */
298 filepath=symget('path
');
299 rc=filename("&fref1",filepath);
301 if did>0 then rc=dclose(did);
302 rc=filename("&fref1");
305 do while(length(directory)>1);
306 if substr(directory,length(directory),1) not in ('/
','\
') then leave;
307 if length(directory)=3 and substr(directory,2,1)=':
' then leave;
308 directory=substr(directory,1,length(directory)-1);
311 file_or_folder='folder
';
313 filename=scan(directory,-1,'/\
');
318 proc append base=&outds data=work.__mp_dirlist_level force nowarn;
322%if %substr(&getattrs,1,1)=Y %then %do;
325 length infoname infoval $60 fref $8;
326 if _n_=1 then call missing(fref);
327 rc=filename(fref,filepath);
328 drop rc infoname fid i close fref;
329 if file_or_folder='file
' then do;
333 putlog "Could not open file:" filepath fid= ;
334 sasname='_MCNOTVALID_
';
337 else do i=1 to foptnum(fid);
338 infoname=foptname(fid,i);
339 infoval=finfo(fid,infoname);
340 sasname=compress(infoname, '_
', 'adik
');
341 if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
342 if upcase(sasname) ne 'FILENAME
' then output;
350 putlog "Could not open folder:" filepath fid= ;
351 sasname='_MCNOTVALID_
';
354 else do i=1 to doptnum(fid);
355 infoname=doptname(fid,i);
356 infoval=dinfo(fid,infoname);
357 sasname=compress(infoname, '_
', 'adik
');
358 if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
359 if upcase(sasname) ne 'FILENAME
' then output;
366 proc transpose data=&outds out=&outds(drop=_:);
369 by filepath file_or_folder filename ext ;
374 set &outds(where=(filepath ne ''));
379drop table work.__mp_dirlist_frontier, work.__mp_dirlist_level;