diff --git a/all.sas b/all.sas index a4980aa..278fcdc 100644 --- a/all.sas +++ b/all.sas @@ -380,7 +380,7 @@ options noquotelenmax; @brief Returns the engine type of a SAS library @details Usage: - %put %mf_getEngine(SASHELP); + %put %mf_getengine(SASHELP); returns: > V9 @@ -398,9 +398,10 @@ options noquotelenmax; @version 9.2 @author Allan Bowe -**/ -%macro mf_getEngine(libref +**/ /** \cond */ + +%macro mf_getengine(libref )/*/STORE SOURCE*/; %local dsid engnum rc engine; @@ -419,7 +420,8 @@ options noquotelenmax; &engine %mend; -/** + +/** \endcond *//** @file @brief Returns the size of a file in bytes. @details Provide full path/filename.extension to the file, eg: @@ -1955,17 +1957,17 @@ run; %mend;/** @file @brief Returns all files and subdirectories within a specified parent - @details When used with getattrs=NO, is not OS specific (uses dopen / dread). + @details When used with getattrs=NO, is not OS specific (uses dopen / dread). If getattrs=YES then the doptname / foptname functions are used to scan all - properties - any characters that are not valid in a SAS name (v7) are simply + properties - any characters that are not valid in a SAS name (v7) are simply stripped, and the table is transposed so theat each property is a column - and there is one file per row. An attempt is made to get all properties + and there is one file per row. An attempt is made to get all properties whether a file or folder, but some files/folders cannot be accessed, and so not all properties can / will be populated. Credit for the rename approach: - https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003 + https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003 usage: @@ -1974,21 +1976,25 @@ run; %mp_dirlist(outds=cwdfileprops, getattrs=YES) - @warning In a Unix environment, the existence of a named pipe will cause this + %mp_dirlist(fref=MYFREF) + + @warning In a Unix environment, the existence of a named pipe will cause this macro to hang. Therefore this tool should be used with caution in a SAS 9 web application, as it can use up all available multibridge sessions if requests are resubmitted. - If anyone finds a way to positively identify a named pipe using SAS (without + If anyone finds a way to positively identify a named pipe using SAS (without X CMD) do please raise an issue! @param path= for which to return contents + @param fref= Provide a DISK engine fileref as an alternative to PATH @param outds= the output dataset to create - @param getattrs= YES/NO (default=NO). Uses doptname and foptname to return - all attributes for each file / folder. + @param getattrs= YES/NO (default=NO). Uses doptname and foptname to return + all attributes for each file / folder. @returns outds contains the following variables: + - directory (containing folder) - file_or_folder (file / folder) - filepath (path/to/file.name) - filename (just the file name) @@ -2001,18 +2007,26 @@ run; **/ %macro mp_dirlist(path=%sysfunc(pathname(work)) + , fref=0 , outds=work.mp_dirlist , getattrs=NO )/*/STORE SOURCE*/; %let getattrs=%upcase(&getattrs)XX; -data &outds (compress=no keep=file_or_folder filepath filename ext msg); - length filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200; - rc = filename(fref, "&path"); +data &outds (compress=no keep=file_or_folder filepath filename ext msg directory); + length directory filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200; + %if &fref=0 %then %do; + rc = filename(fref, "&path"); + %end; + %else %do; + fref="&fref"; + rc=0; + %end; if rc = 0 then do; did = dopen(fref); + directory=dinfo(did,'Directory'); if did=0 then do; - putlog "NOTE: This directory is empty - &path"; + putlog "NOTE: This directory is empty - " directory; msg=sysmsg(); put _all_; stop; @@ -2027,7 +2041,7 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg); dnum = dnum(did); do i = 1 to dnum; filename = dread(did, i); - rc = filename(fref2, "&path/"!!filename); + rc = filename(fref2, cats(directory,'/',filename)); midd=dopen(fref2); dmsg=sysmsg(); if did > 0 then file_or_folder='folder'; @@ -2036,12 +2050,12 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg); fmsg=sysmsg(); if midf > 0 then file_or_folder='file'; rc=fclose(midf); - - if index(fmsg,'File is in use') or index(dmsg,'is not a directory') + + if index(fmsg,'File is in use') or index(dmsg,'is not a directory') then file_or_folder='file'; else if index(fmsg, 'Insufficient authorization') then file_or_folder='file'; else if file_or_folder='' then file_or_folder='locked'; - + if file_or_folder='file' then do; ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename); if filename = ext then ext = ' '; @@ -2074,7 +2088,7 @@ run; else do i=1 to foptnum(fid); infoname=foptname(fid,i); infoval=finfo(fid,infoname); - sasname=compress(infoname, '_', 'adik'); + sasname=compress(infoname, '_', 'adik'); if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname)); if upcase(sasname) ne 'FILENAME' then output; end; @@ -2091,7 +2105,7 @@ run; else do i=1 to doptnum(fid); infoname=doptname(fid,i); infoval=dinfo(fid,infoname); - sasname=compress(infoname, '_', 'adik'); + sasname=compress(infoname, '_', 'adik'); if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname)); if upcase(sasname) ne 'FILENAME' then output; end; @@ -2527,7 +2541,6 @@ create table &outds as datetime2 format or regular decimal type @version 9.3 @author Allan Bowe - @source https://github.com/sasjs/core **/ %macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema= diff --git a/base/mp_dirlist.sas b/base/mp_dirlist.sas index 79b23fa..320922b 100644 --- a/base/mp_dirlist.sas +++ b/base/mp_dirlist.sas @@ -1,17 +1,17 @@ /** @file @brief Returns all files and subdirectories within a specified parent - @details When used with getattrs=NO, is not OS specific (uses dopen / dread). + @details When used with getattrs=NO, is not OS specific (uses dopen / dread). If getattrs=YES then the doptname / foptname functions are used to scan all - properties - any characters that are not valid in a SAS name (v7) are simply + properties - any characters that are not valid in a SAS name (v7) are simply stripped, and the table is transposed so theat each property is a column - and there is one file per row. An attempt is made to get all properties + and there is one file per row. An attempt is made to get all properties whether a file or folder, but some files/folders cannot be accessed, and so not all properties can / will be populated. Credit for the rename approach: - https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003 + https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003 usage: @@ -20,21 +20,25 @@ %mp_dirlist(outds=cwdfileprops, getattrs=YES) - @warning In a Unix environment, the existence of a named pipe will cause this + %mp_dirlist(fref=MYFREF) + + @warning In a Unix environment, the existence of a named pipe will cause this macro to hang. Therefore this tool should be used with caution in a SAS 9 web application, as it can use up all available multibridge sessions if requests are resubmitted. - If anyone finds a way to positively identify a named pipe using SAS (without + If anyone finds a way to positively identify a named pipe using SAS (without X CMD) do please raise an issue! @param path= for which to return contents + @param fref= Provide a DISK engine fileref as an alternative to PATH @param outds= the output dataset to create - @param getattrs= YES/NO (default=NO). Uses doptname and foptname to return - all attributes for each file / folder. + @param getattrs= YES/NO (default=NO). Uses doptname and foptname to return + all attributes for each file / folder. @returns outds contains the following variables: + - directory (containing folder) - file_or_folder (file / folder) - filepath (path/to/file.name) - filename (just the file name) @@ -47,18 +51,26 @@ **/ %macro mp_dirlist(path=%sysfunc(pathname(work)) + , fref=0 , outds=work.mp_dirlist , getattrs=NO )/*/STORE SOURCE*/; %let getattrs=%upcase(&getattrs)XX; -data &outds (compress=no keep=file_or_folder filepath filename ext msg); - length filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200; - rc = filename(fref, "&path"); +data &outds (compress=no keep=file_or_folder filepath filename ext msg directory); + length directory filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200; + %if &fref=0 %then %do; + rc = filename(fref, "&path"); + %end; + %else %do; + fref="&fref"; + rc=0; + %end; if rc = 0 then do; did = dopen(fref); + directory=dinfo(did,'Directory'); if did=0 then do; - putlog "NOTE: This directory is empty - &path"; + putlog "NOTE: This directory is empty - " directory; msg=sysmsg(); put _all_; stop; @@ -73,7 +85,7 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg); dnum = dnum(did); do i = 1 to dnum; filename = dread(did, i); - rc = filename(fref2, "&path/"!!filename); + rc = filename(fref2, cats(directory,'/',filename)); midd=dopen(fref2); dmsg=sysmsg(); if did > 0 then file_or_folder='folder'; @@ -82,12 +94,12 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg); fmsg=sysmsg(); if midf > 0 then file_or_folder='file'; rc=fclose(midf); - - if index(fmsg,'File is in use') or index(dmsg,'is not a directory') + + if index(fmsg,'File is in use') or index(dmsg,'is not a directory') then file_or_folder='file'; else if index(fmsg, 'Insufficient authorization') then file_or_folder='file'; else if file_or_folder='' then file_or_folder='locked'; - + if file_or_folder='file' then do; ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename); if filename = ext then ext = ' '; @@ -120,7 +132,7 @@ run; else do i=1 to foptnum(fid); infoname=foptname(fid,i); infoval=finfo(fid,infoname); - sasname=compress(infoname, '_', 'adik'); + sasname=compress(infoname, '_', 'adik'); if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname)); if upcase(sasname) ne 'FILENAME' then output; end; @@ -137,7 +149,7 @@ run; else do i=1 to doptnum(fid); infoname=doptname(fid,i); infoval=dinfo(fid,infoname); - sasname=compress(infoname, '_', 'adik'); + sasname=compress(infoname, '_', 'adik'); if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname)); if upcase(sasname) ne 'FILENAME' then output; end;