%macro file_finder ( directoryName = , pattern = , depth = 1 , maxDepth = 1 , ddTemp = , outFile = ); %macro unique_filename (prefix=file); %local _i; %let _i=1; %do %while (%sysfunc(fileref(&prefix.&_i.)) <= 0); %let _i=%eval(&_i.+1); %end; &prefix.&_i. %mend; %local rdsAt rdsTempFile; %let rdsAt = @; %let rdsTempFile = %unique_filename; %if (&sysscp. = OS) %then %do; /* Set platform specific at character */ data _null_; call symput ('rdsAt', '7C'x); run; %let directoryName = %upcase (&directoryName.); %let pattern = %upcase (&pattern.); /* Temporary DS to pass commands to IDCAMS */ filename sysin '&sysin' space=(trk,(1,1)) unit=sysda recfm=fb lrecl=80 blksize=23440; /* Temporary DS to capture output from IDCAMS */ filename sysprint '&sysprint' space=(trk,(10,10)) unit=sysda recfm=fba lrecl=133 blksize=23408; /* Write IDCAMS commands */ data _null_; file sysin; PUT " LISTCAT LVL(%upcase(&directoryName.))"; run; /* Call IDCAMS */ proc idcams; run; /* Parse IDCAMS-Output */ data &outFile.; infile sysprint pad; length directoryName pathName fileName $ 42; retain directoryName "&directoryName."; input &rdsAt. 2 _rectype $char8. &rdsAt.; if _rectype = "NONVSAM " then do; input &rdsAt. 18 pathName $char42. /; fileName = substr (pathName, length(trim(directoryName))+2); /* * Test if file can be read. * (It may be locked be a running job.) */ _rc = filename ("&rdsTempFile.", pathName); _did = fopen ("&rdsTempFile.", 'I'); if (_did) then do; output; _did = fclose (_did+0); end; else do; put; put "Note: " pathName "is locked. It will be skipped."; put; end; _rc = filename ("&rdsTempFile."); end; drop _rectype _rc _did; run; %end; %* SYSSCP = OS; %else %do; %local ddFile ddDirectory isExternalCall; %let ddFile = %unique_filename (prefix = f); %let ddDirectory = %unique_filename (prefix = d); %if %length(&ddTemp.) = 0 %then %do; %let isExternalCall = true; data _null_; if (not fileexist("%trim(&directoryName.)")) then put "ERROR: Directory &directoryName. does not exist."; call symput ('pattern', translate ("&pattern.", '%_', '*?')); run; %let ddTemp = %unique_filename (prefix = t); filename &ddTemp. temp; %* Write empty record, in case no file will be found; %let tempFile = %sysfunc(fopen (&ddTemp., a)); %let rc = %qsysfunc (fput (&tempFile., _)); %let rc = %sysfunc(fwrite (&tempFile.)); %let tempFile = %sysfunc(fclose (&tempFile.)); %end; %else %do; %let isExternalCall = false; %end; %local directory i fileName pathName file; %* Allocate and open directory to be searched; %let rc = %sysfunc (filename (ddDirectory, &directoryName.)); %let directory = %sysfunc (dopen (&ddDirectory.)); %if (&directory. ne 0) %then %do i=1 %to %sysfunc (dnum (&directory.)); %* Read next file entry; %let fileName = %sysfunc (dread (&directory., &i.)); %let pathName = &directoryName./&fileName.; %* It is a file if we can issue FOPEN; %let rc = %sysfunc (filename (ddFile, &pathName.)); %let file = %sysfunc(fopen (&ddFile., i)); %if &file. ne 0 %then %do; %* Entry is a file ... close an free; %let file = %sysfunc(fclose (&file.)); %let rc = %sysfunc (filename (ddFile)); %* Write file to temporary file; %let tempFile = %sysfunc(fopen (&ddTemp., a)); %let rc = %qsysfunc (fput (&tempFile., &directoryName.)); %let rc = %sysfunc(fwrite (&tempFile.)); %let rc = %qsysfunc (fput (&tempFile., &fileName.)); %let rc = %sysfunc(fwrite (&tempFile.)); %let rc = %qsysfunc (fput (&tempFile., &pathName.)); %let rc = %sysfunc(fwrite (&tempFile.)); %* Close temporary file; %let tempFile = %sysfunc(fclose (&tempFile.)); %end; %else %do; %* Entry is a directory ... free; %let rc = %sysfunc (filename (ddFile)); %* Call macro recursively; %if &maxDepth = 0 or &depth. < &maxDepth. %then %do; %file_finder ( directoryName = &pathName. , depth = %eval (&depth.+1) , maxDepth = &maxDepth. , ddTemp = &ddTemp. ); %end; %end; %end; %* All files of current directory; %else %do; %put; %put Note: &directoryName. is not a directory or it is a file; %put which is currently locked. It will be skipped.; %put; %end; %* Close an free directory; %let directory = %sysfunc(dclose (&directory.)); %let rc = %sysfunc (filename (ddDirectory)); %if (&isExternalCall = true) %then %do; data &outFile.; infile &ddTemp. firstobs=2; input; directoryName = _infile_; input; fileName = _infile_; input; pathName = _infile_; run; filename &ddTemp.; proc sql; delete from &outFile. where fileName not like "&pattern."; quit; %end; %end; %* SYSSCP not= OS; %mend file_finder;