This program searches for a specific string in various directories on my computer. After running it asks to input a string and also to select a specific directory. I just want this program to search all directories at once so that I don't have to select and search them one by one.
%global fnobs dir ext;
%let ext = SAS; /*file extension*/
%let string = %UPCASE(&SEARCH_STRING);
%PUT &STRING;
proc datasets nolist;
delete all;
run;
%MACRO SETDIR;
%IF &DBSYS = CboTestEditValidation %THEN
%DO;
%LET DBSYS=CBO_2324_TEST_EDIT_VALIDATION;
%LET DIR=\\edw-fs02\CAE_Data\CBO\&Year\Programs;
%END;
%ELSE %IF &DBSYS = CBOSurveyReports %then %do;
%let dbsys = CBO-Survey-Reports-Programs;
%LET DIR=\\edw-fs02\CAE_Data\CBO\CBO Survey Reports\&Year;
%end;
%ELSE %IF &DBSYS = WDISPrograms %then %do;
%let dbsys = WDIS;
%LET DIR=\\edw-fs02\CAE_Data\WDIS\PRODUCTION\Survey Reports\&Year;
%end;
%ELSE %IF &DBSYS = SECCTEAppendixFF %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\APPENDICES_WDIS_SECCTE\SECCTE\FF_appendixff_xls;
%end;
%ELSE %IF &DBSYS = SECCTEAppendixY %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\APPENDICES_WDIS_SECCTE\SECCTE\Y_appendixy_xls;
%end;
%ELSE %IF &DBSYS = WDISAppendixH %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\APPENDICES_WDIS_SECCTE\WDIS\H_appendixh_xls;
%end;
%ELSE %IF &DBSYS = WDISAppendixO %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\APPENDICES_WDIS_SECCTE\WDIS\O_appendixo_xls;
%end;
%ELSE %IF &DBSYS = WDISAppendixP %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\APPENDICES_WDIS_SECCTE\WDIS\P_appendixp_xls;
%end;
%ELSE %IF &DBSYS = WDISAppendixQ %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\APPENDICES_WDIS_SECCTE\WDIS\Q_appendixq_xls;
%end;
%ELSE %IF &DBSYS = SECCTEWDISAppendixZ %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\APPENDICES_WDIS_SECCTE\WDIS_SECCTE_AppendixZ_2324;
%end;
%ELSE %IF &DBSYS = BuildCIPSupportFiles %then %do;
%let dbsys = Appendix;
%LET DIR="\\edw-fs02\CAE_Data\CIPS\2023-2024\Build CIP and Support Files";
%end;
%ELSE %IF &DBSYS = 2324WDISReferenceTables %then %do;
%let dbsys = Appendix;
%LET DIR=\\edw-fs02\CAE_Data\CIPS\2023-2024\2324 WDIS REFERENCE TABLES;
%end;
/*%ELSE %IF &DBSYS = CBO2324SurveyReports %then %do;
%let dbsys = CBO-2324-Survey-Reports-Programs;
%LET DIR=\\edw-fs02\CAE_Data\CBO\CBO Survey Reports\2324;
%end;
%ELSE %IF &DBSYS = CBO2425SurveyReports %then %do;
%let dbsys = CBO-2425-Survey-Reports-Programs;
%LET DIR=\\edw-fs02\CAE_Data\CBO\CBO Survey Reports\2425;
%end;
%ELSE %IF &DBSYS = CBO2526SurveyReports %then %do;
%let dbsys = CBO-2526-Survey-Reports-Programs;
%LET DIR=\\edw-fs02\CAE_Data\CBO\CBO Survey Reports\2526;
%end;
%ELSE %IF &DBSYS = WDISPrograms2324 %then %do;
%let dbsys = WDIS-2324;
%LET DIR=\\edw-fs02\CAE_Data\WDIS\PRODUCTION\Survey Reports\2324;
%end;
%ELSE %IF &DBSYS = WDISPrograms2425 %then %do;
%let dbsys = WDIS-2425;
%LET DIR=\\edw-fs02\CAE_Data\WDIS\PRODUCTION\Survey Reports\2425;
%end;
%ELSE %IF &DBSYS = WDISprograms2526 %then %do;
%let dbsys = WDIS-2526;
%LET DIR=\\edw-fs02\CAE_Data\WDIS\PRODUCTION\Survey Reports\2526;
%end;*/
%ELSE %LET DIR=\\edw-fs02\CAE_Data\WDIS\PRODUCTION\Survey Reports\2324;
%PUT &DIR;
%MEND SETDIR;
%SETDIR;
RUN;
%MACRO SETOBS (DSET);
DATA _NULL_;
DSID=OPEN("&DSET");
IF (DSID = 0) THEN DO;
PUT 'FILE NOT OPENED';
END;
ELSE DO;
PUT 'DSET DATA SET HAS BEEN OPENED';
ISOBS=ATTRN(DSID,'NOBS');
IF ISOBS GT -1 THEN DO;
CALL SYMPUT ("FNOBS",RIGHT(PUT(ISOBS,8.)));
END;
END;
RUN;
%MEND SETOBS;
%macro list_members;
%global dnum;
data tibco_list(KEEP=filename ext);
format fref $char8. filename $char256. filetype $char100. CCNUM 8. CCNUMX $char2. colname $char50. sub $char1. trm 1. year $char4. dbtype $char3.
ext $char3.;
rc = filename(fref,"&DIR");
if rc = 0 then
do;
did = dopen(fref);
rc = filename(fref);
end;
else
do;
length msg $200.;
msg = sysmsg();
put msg=;
did = .;
end;
if did <= 0 then
putlog 'ERR' 'OR: Unable to open directory.';
dnum = dnum(did);
call symput("dnum",dnum);
fcount = 0;
%PUT &DNUM;
do j = 1 to dnum;
filename = dread(did, j);
putlog filename=;
fid = mopen(did, filename);
ext=upcase(scan(filename,-1,'.'));
NUMDOTS = count(filename,'.');
putlog numdots=;
IF ext IN ('SAS', 'egp') THEN
output tibco_list;
end;
rc = dclose(did);
run;
%mend list_members;
%list_members;
RUN;
%macro readraw;
%SETOBS(tibco_list);
DATA tibco_list;
SET tibco_list NOBS=NOBS;
RETAIN SEQ;
SEQ=SUM(SEQ,1);
RUN;
%let rc=%sysfunc(filename(fileref,%superq(dir)));
%let did=%sysfunc(dopen(&fileref));
%do dmem=1 %to &fnobs;
DATA _NULL_;
SET tibco_list;
WHERE SEQ = &dmem;
CALL SYMPUT("memname",trim(filename));
RUN;
*--this is telling the code that we are only interested in files that have an extension of SAS;
%if %qupcase(%qscan(%superq(memname),-1,.))=&ext. %then
%do;
*--depending on the file type you are looking at, you may need another method to read in the file contents;
data temp;
length program $3600.;
infile "&dir.\&memname." truncover;
input @01 line $char2500.;
line_num=_n_;
program="&dir\&memname.";
if index(upcase(line), "&STRING") > 0 then
do;
line_num=_n_;
program="&dir\&memname.";
output;
end;
run;
proc append data=temp base=all;
run;
%end;
%end;
%let dsid = %sysfunc(open(all));
*-- If the data set exists, then grab the number of observations and variables;
*-- then close the data seth;
%if &dsid %then
%do;
%let nobs =%sysfunc(attrn(&dsid,nobs));
%let rc = %sysfunc(close(&dsid));
%put &nobs;
%if &nobs > 0 %then
%do;
proc print data=all noobs;
title "Looking for &string.";
title2 " &string found in the following programs";
run;
%end;
%else %put NOTE: &string not found in &dir.;
%end;
%let didc=%sysfunc(dclose(%nrbquote(&did)));
%let rc=%sysfunc(filename(fileref));
%mend readraw;
%readraw;
run;
For a head start, I have a ready-made macro (%findfiles) that can traverse directories and produce either a list of files with a specified extension in the log
or write them to a SAS dataset.
SYNTAX:
%FindFiles(dir,<ext,dsn,sub>)
dir=fully qualified directory path
ext=Space delimited list of file extensions (Optional, default is ALL)
dsn=name of data set to store filenames (Optional, otherwise writes to log.)
sub=look in subfolders? (Y|N default is Y)
Examples:
%FindFiles(c:\temp, csv)
%FindFiles(\\server\folder\, xls xlsx xlsm, work.myfiles)
%FindFiles(s:/workshop,sas,work.pgm_files,N)
This macro depends on three utility macros ( %exist, %fileattribs, and %translate). You can download the files from my GitHub sas-macros repository, or use this SAS code to download them:
%let path=<your custom macro storage location>;
filename maccode "&path/exists.sas";
proc http url="https://github.com/SASJedi/sas-macros/raw/master/exist.sas" out=maccode;
run;
filename maccode2 "&path/fileattribs.sas";
proc http url="https://github.com/SASJedi/sas-macros/raw/master/fileattribs.sas" out=maccode2;
run;
filename maccode3 "&path/translate.sas";
proc http url="https://github.com/SASJedi/sas-macros/raw/master/translate.sas" out=maccode3;
run;
filename maccode4 "&path/findfiles.sas";
proc http url="https://github.com/SASJedi/sas-macros/raw/master/findfiles.sas" out=maccode4;
run;
Examine the files you downloaded to see how the code works and to ensure there's nothing nefarious going on there, if you wish.
/* After examining the code you downloaded, run the macro programs to compile the macors */
%include maccode;
%include maccode2;
%include maccode3;
%include maccode4;
filename maccode clear;
filename maccode2 clear;
filename maccode3 clear;
filename maccode4 clear;
/*Get syntax help in the log for any macro using ? as the only parameter value:*/
%findfiles(?)
You can then use the dataset you created to drive the rest of your process...
For example, I ran this on my computer:
%FindFiles(D:/Courses/PG1V2, xls xlsx xlsm, work.myfiles)
proc print noobs; run;
And this was the result:
Item | Path | Filename | Size | CRDate | CRTime | ModDate | ModTime |
---|---|---|---|---|---|---|---|
1 | D:/Courses/PG1V2/data | class.xlsx | 10,000 | 06/12/2023 | 7:51:04 | 12/08/2017 | 12:13:00 |
2 | D:/Courses/PG1V2/data | eu_sport_trade.xlsx | 234,100 | 06/12/2023 | 7:51:04 | 12/19/2017 | 14:48:36 |
3 | D:/Courses/PG1V2/data | np_info.xlsx | 7,234,320 | 06/12/2023 | 7:51:04 | 01/30/2018 | 13:26:40 |
4 | D:/Courses/PG1V2/data | storm.xlsx | 6,859,276 | 06/12/2023 | 7:51:04 | 12/05/2019 | 12:51:42 |
Hope that helps.
Which operating system?
DOS (and WIndows still supports Dos commands) FINDSTR
UNIX and derivative operating systems the GREP command does this
I would start with OS commands instead of writing from scratch as many of those are already set up to do directory and subdirectory searches.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Select SAS Training centers are offering in-person courses. View upcoming courses for: