I'm trying to get a list of files in a directory and the subdirectories with file attributes, in particular the size of each file.
the files are listed in the main directory, but there a bunch of subdirectories with files. I've been using the following code, but
have not figured out how to get the size of the file, it only gives the directory and file. I've used the FINFO function, but doesn't give the size.
%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;*/
%if %qscan(&name,2,.) ne %then %do;
%put &dir/&name;
data _tmp;
length dir $512 name $100;
dir=symget("dir");
name=symget("name");
size=FINFO(OPEN(symget("name")), 'FILE SIZE (BYTES)');
run;
proc append base=want
data =_tmp;
run;quit;
%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(/gpfsFS2/sasdata/adhoc/pofin/nps/npsts/prod/cera/data,*)
If you have XCMD enabled, use the proper external command (find with .ls) in a FILENAME PIPE and read the output.
If not, here's a very neat piece of code from @Tom that does it in a single data step:
data filelist;
length dname filename $256 dir level 8 lastmod size 8;
format lastmod datetime20.;
input dname;
retain filename ' ' level 0 dir 1;
cards4;
/folders/myfolders
;;;;
data filelist;
modify filelist;
rc1=filename('tmp',catx('/',dname,filename));
rc2=dopen('tmp');
dir = not not rc2;
if not dir then do;
fid=fopen('tmp','i',0,'b');
lastmod=input(finfo(fid,foptname(fid,5)),NLDATM100.);
size=input(finfo(fid,foptname(fid,6)),32.);
fid=fclose(fid);
end;
else do;
dname=catx('/',dname,filename);
filename=' ';
lastmod=input(dinfo(rc2,doptname(rc2,5)),NLDATM100.);
end;
replace;
if dir;
level=level+1;
do i=1 to dnum(rc2);
filename=dread(rc2,i);
output;
end;
rc3=dclose(rc2);
run;
Try the FOPEN function. The OPEN function is for SAS datasets.
Also I think you need to assign a FILEREF for the file you want to open then refer to that, not the actual file name:
rc=filename("curdirfl", "c:\temp\MytestFile.txt"); fid=fopen("curdirfl", "i") ;
If you have XCMD enabled, use the proper external command (find with .ls) in a FILENAME PIPE and read the output.
If not, here's a very neat piece of code from @Tom that does it in a single data step:
data filelist;
length dname filename $256 dir level 8 lastmod size 8;
format lastmod datetime20.;
input dname;
retain filename ' ' level 0 dir 1;
cards4;
/folders/myfolders
;;;;
data filelist;
modify filelist;
rc1=filename('tmp',catx('/',dname,filename));
rc2=dopen('tmp');
dir = not not rc2;
if not dir then do;
fid=fopen('tmp','i',0,'b');
lastmod=input(finfo(fid,foptname(fid,5)),NLDATM100.);
size=input(finfo(fid,foptname(fid,6)),32.);
fid=fclose(fid);
end;
else do;
dname=catx('/',dname,filename);
filename=' ';
lastmod=input(dinfo(rc2,doptname(rc2,5)),NLDATM100.);
end;
replace;
if dir;
level=level+1;
do i=1 to dnum(rc2);
filename=dread(rc2,i);
output;
end;
rc3=dclose(rc2);
run;
Can we get the owner of the file/directory as well (ie:who created/modified)
You can get the owner, but not the modifier if that is different from the owner (if a file is group-and/or world-writable). Modifiers are not recorded in any operating system I know of, unless you run some kind of auditing software; in which case, the modifier would still not be stored in file metadata, but in a separate database.
The owner is file info item #2 (at least on UNIX).
See this example code to get a feel for the construct:
data check;
length fref $8;
fid = filename(fref,"insert your file path here");
fid = fopen(fref);
do i = 1 to foptnum(fid);
opt = foptname(fid,i);
value = finfo(fid,opt);
output;
end;
fid = fclose(fid);
fid = filename(fref);
run;
This will show you all available information items for your platform, and the values for the file selected.
How to use it?!
14815 data check;
14816 length fref $8;
14817 fid = filename(fref,"d:\");
14818 fid = fopen(fref);
14819 do i = 1 to foptnum(fid);
14820 opt = foptname(fid,i);
14821 value = finfo(fid,opt);
14822 output;
14823 end;
14824 fid = fclose(fid);
14825 fid = filename(fref);
14826 run;
This is a great solution.
Do you know how I can add the owner (person who created the files) to the report?
This is the code I am usign - copied from this blog
I need to add the owner of the files - so we can send out reports to the owners to delete obsolete files.
data filelist;
length dname filename $256 dir level 8 lastmod size 8 user $32 ;
format lastmod datetime20.;
input dname;
retain filename ' ' level 0 dir 1;
cards4;
/sas/analytics/sasdata/users
/sas/analytics/projects
;;;;
data filelist;
modify filelist;
rc1=filename('tmp',catx('/',dname,filename));
rc2=dopen('tmp');
dir = not not rc2;
if not dir then do;
fid=fopen('tmp','i',0,'b');
lastmod=input(finfo(fid,foptname(fid,5)),NLDATM100.);
size=input(finfo(fid,foptname(fid,6)),32.);
fid=fclose(fid);
end;
else do;
dname=catx('/',dname,filename);
filename=' ';
lastmod=input(dinfo(rc2,doptname(rc2,5)),NLDATM100.);
end;
replace;
if dir;
level=level+1;
do i=1 to dnum(rc2);
filename=dread(rc2,i);
output;
end;
rc3=dclose(rc2);
run;
Add it here:
if not dir then do;
fid=fopen('tmp','i',0,'b');
owner = finfo(fid,foptname(fid,2));
lastmod=input(finfo(fid,foptname(fid,5)),NLDATM100.);
size=input(finfo(fid,foptname(fid,6)),32.);
fid=fclose(fid);
end;
Set a proper length for the variable.
Thank you, it worked!
How does one use this code? Is it only replacing the "/folders/myfolders" with the desired directory?
Thanks
@torvyle wrote:
How does one use this code? Is it only replacing the "/folders/myfolders" with the desired directory?
Thanks
You insert the root directories of the trees you want to search in in the DATALINES block of the first data step (replace /folders/myfolders, as that was the data directory used in the no longer available SAS University Edition).
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.