Hi, I am using SAS University Edition and trying to get names of all the file available in a Folder (Folder inside Shared Folder). So that, I can prepared a Macro to import and append all the data sets in one.
I need help to get names for all the CSV files available in my Folder.
Use the built-in SAS functions:
data filenames;
length fref $8 fname $200;
did = filename(fref,'/folders/myfolders');
did = dopen(fref);
do i = 1 to dnum(did);
fname = dread(did,i);
output;
end;
did = dclose(did);
did = filename(fref);
keep fname;
run;
This question has been asked over and over. Maybe this topic should be a sticky @AnnaBrown @BeverlyBrown ?
Search list files for example.
Out of many replies, here is a clever way, devised by Tom.
data FILELIST;
format DIR LEVEL 3. PATH FILENAME $256. LASTMOD datetime.;
retain DIR 0 LEVEL -1 FILENAME ' ' LASTMOD .;
input PATH;
cards;
c:\temp\
x:\
run;
data FILELIST;
retain SEP "%sysfunc(ifc(&sysscp=WIN,\,/))";
modify FILELIST;
RC = filename('tmp',catx(SEP, PATH, FILENAME));
DIRID = dopen('tmp');
DIR = (DIRID>0);
if DIR then do;
PATH = catx(SEP, PATH, FILENAME);
FILENAME = ' ';
if SEP='/' then LASTMOD = input(dinfo(DIRID, doptname(DIRID, 5)), nldatm100.);
replace;
DIR =0;
LEVEL=LEVEL+1;
do I=1 to dnum(DIRID);
FILENAME=dread(DIRID, I);
output;
end;
RC=dclose(DIRID);
end;
else if scan(FILENAME,-1,'.') ne 'lck' then do;
FID=fopen('tmp','i',0,'b');
%* == FOPTNAME values for single files ==
Unix Win
1 Filename Filename
2 Owner name RECFM
3 Group name LRECL
4 Access Permission File Size (bytes)
5 Last Modified Last Modified
6 File Size (bytes) Create Time ;
if FID then do;
LASTMOD = input(finfo(FID, foptname(FID, 5)), nldatm100.);
SIZE = input(finfo(FID, foptname(FID, ifn(SEP='/',6,4))), 32.);
RC = fclose(FID);
replace;
end;
end;
run;
Yet another approach...
https://github.com/scottbass/SAS/blob/master/Macro/dirlist.sas
I do this enough to have a macro for it. There are some dependencies on other macros I've written. You can try it yourslef :
/* Get the necessary macro files */
filename getmacro url "https://raw.githubusercontent.com/SASJedi/sas-macros/master/exist.sas";
%include getmacro;
filename getmacro url "https://raw.githubusercontent.com/SASJedi/sas-macros/master/fileattribs.sas";
%include getmacro;
filename getmacro url "https://raw.githubusercontent.com/SASJedi/sas-macros/master/translate.sas";
%include getmacro;
filename getmacro url "https://raw.githubusercontent.com/SASJedi/sas-macros/master/findfiles.sas";
%include getmacro;
/* Get syntax help in the log */
%FindFiles(?)
/* List files in the s:/workshop and all sub-folders, save as a SAS data set */
%FindFiles(s:/workshop,,work.myFiles)
Use the built-in SAS functions:
data filenames;
length fref $8 fname $200;
did = filename(fref,'/folders/myfolders');
did = dopen(fref);
do i = 1 to dnum(did);
fname = dread(did,i);
output;
end;
did = dclose(did);
did = filename(fref);
keep fname;
run;
It first creates a file reference for the directory (FILENAME), opens the directory and creates a handle (DOPEN), and then loops over all (DNUM) entries in the directory and reads each (DREAD). At the end, it deassigns the handle and the file reference.
I recommend studying the documentation of all these functions.
I wrote a macro that allows recursive functionality and adds FINFO data. This works on both Windows and Linux, even when the X statement cannot be used. On LSAF, the datetime stamps are moot since the file is copied to the transient directory.
HTH,
Kevin
@Kevin_Viel wrote:
I wrote a macro that allows recursive functionality and adds FINFO data.
You're not the first one 😉
No doubt and I did not search, but it might make a suitable SUG paper if one does not already exist or does not have some functionalities. I use it quite frequently. I have read entire directories in minutes, which is fast given the structure and volume, but I am sure it could be faster.
I would have presented it this year in Washington (was an invited speaker), but COVID ...
Actually, a complete session about interacting with the base operating system, with and without XCMD.
I plan it for the next in-person Global Forum.
You can also see an example from SAS Documentation , a dynamic way of doing this
A Macro which gets you Sub Dir and File Names
%macro list_files(dir,ext);
%local filrf rc did memcnt name i;
%let rc=%sysfunc(filename(filrf,&dir));
%let did=%sysfunc(dopen(&filrf));
%if &did eq 0 %then %do;
%put Directory &dir cannot be open or does not exist;
%return;
%end;
%do i = 1 %to %sysfunc(dnum(&did));
%let name=%qsysfunc(dread(&did,&i));
%if %qupcase(%qscan(&name,-1,.)) = %upcase(&ext) %then %do;
%put &dir\&name;
%end;
%else %if %qscan(&name,2,.) = %then %do;
%list_files(&dir\&name,&ext)
%end;
%end;
%let rc=%sysfunc(dclose(&did));
%let rc=%sysfunc(filename(filrf));
%mend list_files;
%list_files(c:\temp,sas)
@LittlesasMaster wrote:
You can also see an example from SAS Documentation , a dynamic way of doing this
A Macro which gets you Sub Dir and File Names
%macro list_files(dir,ext); %local filrf rc did memcnt name i; %let rc=%sysfunc(filename(filrf,&dir)); %let did=%sysfunc(dopen(&filrf)); %if &did eq 0 %then %do; %put Directory &dir cannot be open or does not exist; %return; %end; %do i = 1 %to %sysfunc(dnum(&did)); %let name=%qsysfunc(dread(&did,&i)); %if %qupcase(%qscan(&name,-1,.)) = %upcase(&ext) %then %do; %put &dir\&name; %end; %else %if %qscan(&name,2,.) = %then %do; %list_files(&dir\&name,&ext) %end; %end; %let rc=%sysfunc(dclose(&did)); %let rc=%sysfunc(filename(filrf)); %mend list_files; %list_files(c:\temp,sas)
This macro looping would be orders of magnitude slower than using corresponding functions in a data step, although it does have the benefit of being recursive.
That is a simple approach if the number of files is small and the file sizes are also small. It is a good demonstration. For a single level, i.e. not recursive, Kurt snippet is a great approach. Have you tried this with other file formats, life PDF? I suspect it would still work. I also wonder about using *.*?
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.