Production Ready Macros for SAS Application Developers
https://github.com/sasjs/core
mp_dirlist.sas
Go to the documentation of this file.
1 /**
2  @file
3  @brief Returns all files and subdirectories within a specified parent
4  @details When used with getattrs=NO, is not OS specific (uses dopen / dread).
5 
6  If getattrs=YES then the doptname / foptname functions are used to scan all
7  properties - any characters that are not valid in a SAS name (v7) are simply
8  stripped, and the table is transposed so theat each property is a column
9  and there is one file per row. An attempt is made to get all properties
10  whether a file or folder, but some files/folders cannot be accessed, and so
11  not all properties can / will be populated.
12 
13  Credit for the rename approach:
14  https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
15 
16 
17  usage:
18 
19  %mp_dirlist(path=/some/location,outds=myTable)
20 
21  %mp_dirlist(outds=cwdfileprops, getattrs=YES)
22 
23  @warning In a Unix environment, the existence of a named pipe will cause this
24  macro to hang. Therefore this tool should be used with caution in a SAS 9 web
25  application, as it can use up all available multibridge sessions if requests
26  are resubmitted.
27  If anyone finds a way to positively identify a named pipe using SAS (without
28  X CMD) do please raise an issue!
29 
30 
31  @param path= for which to return contents
32  @param outds= the output dataset to create
33  @param getattrs= YES/NO (default=NO). Uses doptname and foptname to return
34  all attributes for each file / folder.
35 
36 
37  @returns outds contains the following variables:
38  - file_or_folder (file / folder)
39  - filepath (path/to/file.name)
40  - filename (just the file name)
41  - ext (.extension)
42  - msg (system message if any issues)
43  - OS SPECIFIC variables, if <code>getattrs=</code> is used.
44 
45  @version 9.2
46  @author Allan Bowe
47 **/
48 
49 %macro mp_dirlist(path=%sysfunc(pathname(work))
50  , outds=work.mp_dirlist
51  , getattrs=NO
52 )/*/STORE SOURCE*/;
53 %let getattrs=%upcase(&getattrs)XX;
54 
55 data &outds (compress=no keep=file_or_folder filepath filename ext msg);
56  length filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200;
57  rc = filename(fref, "&path");
58  if rc = 0 then do;
59  did = dopen(fref);
60  if did=0 then do;
61  putlog "NOTE: This directory is empty - &path";
62  msg=sysmsg();
63  put _all_;
64  stop;
65  end;
66  rc = filename(fref);
67  end;
68  else do;
69  msg=sysmsg();
70  put _all_;
71  stop;
72  end;
73  dnum = dnum(did);
74  do i = 1 to dnum;
75  filename = dread(did, i);
76  rc = filename(fref2, "&path/"!!filename);
77  midd=dopen(fref2);
78  dmsg=sysmsg();
79  if did > 0 then file_or_folder='folder';
80  rc=dclose(midd);
81  midf=fopen(fref2);
82  fmsg=sysmsg();
83  if midf > 0 then file_or_folder='file';
84  rc=fclose(midf);
85 
86  if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
87  then file_or_folder='file';
88  else if index(fmsg, 'Insufficient authorization') then file_or_folder='file';
89  else if file_or_folder='' then file_or_folder='locked';
90 
91  if file_or_folder='file' then do;
92  ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename);
93  if filename = ext then ext = ' ';
94  end;
95  else do;
96  ext='';
97  file_or_folder='folder';
98  end;
99  filepath="&path/"!!filename;
100  output;
101  end;
102  rc = dclose(did);
103  stop;
104 run;
105 
106 %if %substr(&getattrs,1,1)=Y %then %do;
107  data &outds;
108  set &outds;
109  length infoname infoval $60 fref $8;
110  rc=filename(fref,filepath);
111  drop rc infoname fid i close fref;
112  if file_or_folder='file' then do;
113  fid=fopen(fref);
114  if fid le 0 then do;
115  msg=sysmsg();
116  putlog "Could not open file:" filepath fid= ;
117  sasname='_MCNOTVALID_';
118  output;
119  end;
120  else do i=1 to foptnum(fid);
121  infoname=foptname(fid,i);
122  infoval=finfo(fid,infoname);
123  sasname=compress(infoname, '_', 'adik');
124  if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
125  if upcase(sasname) ne 'FILENAME' then output;
126  end;
127  close=fclose(fid);
128  end;
129  else do;
130  fid=dopen(fref);
131  if fid le 0 then do;
132  msg=sysmsg();
133  putlog "Could not open folder:" filepath fid= ;
134  sasname='_MCNOTVALID_';
135  output;
136  end;
137  else do i=1 to doptnum(fid);
138  infoname=doptname(fid,i);
139  infoval=dinfo(fid,infoname);
140  sasname=compress(infoname, '_', 'adik');
141  if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
142  if upcase(sasname) ne 'FILENAME' then output;
143  end;
144  close=dclose(fid);
145  end;
146  run;
147  proc sort;
148  by filepath sasname;
149  proc transpose data=&outds out=&outds(drop=_:);
150  id sasname;
151  var infoval;
152  by filepath file_or_folder filename ext ;
153  run;
154 %end;
155 %mend;