BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
sam1231
Obsidian | Level 7
Below macro read files from directory but i want to add code so it can read files from sub-directory

What can i do
%macro dir_contents(
dir= /* directory name to process */
, ext= /* optional extension to filter on */
, dsout=work.dir_contents /* dataset name to hold the file names */
, attribs=N /* get file attributes? (Y/N ) */
);

%global _dir_fileN; %local _syspathdlim _exitmsg _attrib_vars; %* verify the required parameter has been provided. ; %if %length(&dir) = 0 %then %do; %let _exitmsg = %str(E)RROR: No directory name specified - macro will exit.; %goto finish; %end; %* verify existence of the requested directory name. ; %if %sysfunc(fileexist(&dir)) = 0 %then %do; %let _exitmsg = %str(E)RROR: Specified input location, &dir., does not exist - macro will exit.; %goto finish; %end; %* set the separator character needed for the full file path: ; %* (backslash for Windows, forward slash for UNIX systems) ; %if &sysscp = WIN %then %do; %let _syspathdlim = \; %end; %else %do; %let _syspathdlim = /; %end; /*--- begin data step to capture names of all file names found in the specified directory. ---*/ data &dsout(keep=file_seq basefile pathname); length basefile $ 40 pathname $ 1000 _msg $ 1000; /* Allocate directory */ rc=FILENAME('xdir', "&dir"); if rc ne 0 then do; _msg = "E" || 'RROR: Unable to assign fileref to specified directory. ' || sysmsg(); go to finish_datastep; end; /* Open directory */ dirid=DOPEN('xdir'); if dirid eq 0 then do; _msg = "E" || 'RROR: Unable to open specified directory. ' || sysmsg(); go to finish_datastep; end; /* Get number of information items */ nfiles=DNUM(dirid); do j = 1 to nfiles; basefile = dread(dirid, j); pathname=strip("&dir") || "&_syspathdlim." || strip(basefile); %if %length(&ext) %then %do; /* scan the final "word" of the full file name, delimited by dot character. */ ext = scan(basefile,-1,'.'); if ext="&ext." then do; file_seq + 1; output; end; %end; %else %do; file_seq + 1; output; %end; end; /* Close the directory */ rc=DCLOSE(dirid); /* Deallocate the directory */ rc=FILENAME('xdir'); call symputx('_dir_fileN', file_seq); finish_datastep: if _msg ne ' ' then do; call symput('_exitmsg', _msg); end; run; %if %upcase(&attribs)=Y and &_dir_fileN > 0 %then %do; data _file_attr(keep=file_seq basefile infoname infoval); length infoname infoval $ 500; set &dsout.; /* open each file to get the additional attributes available. */ rc=filename("afile", pathname); fid=fopen("afile"); /* return the number of system-dependent information items available for the external file. */ infonum=foptnum(fid); /* loop to get the name and value of each information item. */ do i=1 to infonum; infoname=foptname(fid,i); infoval=finfo(fid,infoname); if upcase(infoname) ne 'FILENAME' then output; end; close=fclose(fid); run; /* transpose each information item into its own variable */ proc transpose data=_file_attr out=trans_attr(drop=_:) ; by file_seq basefile ; var infoval; id infoname; run; proc sql noprint; select distinct name into : _attrib_vars separated by ', ' from dictionary.columns where memname='TRANS_ATTR' and upcase(name) not in('BASEFILE', 'FILE_SEQ') order by varnum; quit; /* merge back the additional attributes to the related file name. */ data &dsout.; merge &dsout. trans_attr; by file_seq basefile; run; proc datasets nolist memtype=data lib=work; delete _file_attr trans_attr; run; quit; %end; %if %length(&_exitmsg) = 0 %then %let _exitmsg = NOTE: &dsout created with &_dir_fileN. file names ; %if %length(&ext) %then %let _exitmsg = &_exitmsg where extension is equal to &ext.; %let _exitmsg = &_exitmsg from &dir..; %finish: %put &_exitmsg; %if %length(&_attrib_vars) ne 0 %then %do; %put; %put NOTE: File attributes were requested and have been added to &dsout.. Variable names are &_attrib_vars.; %end;

 

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User
 %let _exitmsg = %str(E)RROR 

if rc ne 0 then do; _msg = "E" || 'RROR: Unable to assign fileref to specified directory. ' || sysmsg();

?????? Why the %str?   Why "E"|| 'RROR:  ???

 

 

Suggest also looking at the CAT functions instead of || operator for concatenating

View solution in original post

2 REPLIES 2
Kurt_Bremser
Super User

Crushing peanuts with an elephant's hoof. This can be achieved in a much simpler way by using the power of your operating system:

filename oscmd pipe "find /path -name \*.csv";

data _null_;
infile oscmd;
input;
call execute('%nrstr(%import_file(' !! strip(_infile_) !! '))');
run;

if you have a macro for importing a single file. Expand this step as needed.

ballardw
Super User
 %let _exitmsg = %str(E)RROR 

if rc ne 0 then do; _msg = "E" || 'RROR: Unable to assign fileref to specified directory. ' || sysmsg();

?????? Why the %str?   Why "E"|| 'RROR:  ???

 

 

Suggest also looking at the CAT functions instead of || operator for concatenating

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 2 replies
  • 3414 views
  • 1 like
  • 3 in conversation