My final version then, which works for windows and Unix:
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;
No dinfo() data for Windows, and locked .lck files were giving me errors upon using fopen() under Unix.
As kurt said, it's a shame some metadata can only be obtained via the CLI.
[Edited as one line was dropped off...]
I recently posted a ballot idea that the file functions (fopen, foptnum, foptname, finfo) be enabled to also work with directory files; that would deal with this problem.
Thanks All.
I can accept this as a solution. how can I convert them into GB rather than in bytes.
i think ,by doing divided by 1024.
Divide by 1024, and you get the size in K. Divide again, and you get size in M. Divide again, and you get size in G.
So the size in G is
size_in_bytes / (1024 * 1024 * 1024)
@Tom , great way to enable a pseudo-recursion within a data step. Kudos.
Here is a working version for Windows
I added a provision for locked files (FID=0) and for the date format being different from Unix.
data FILELIST;
retain SEP "%sysfunc(ifc(&sysscp=WIN,\,/))";
modify FILELIST;
RC1 = filename('tmp',catx(SEP, DNAME, FILENAME));
RC2 = dopen('tmp');
DIR = (RC2>0);
if not DIR then do;
FID=fopen('tmp','i',0,'b');
if FID then do;
LASTMOD=input(finfo(FID, foptname(FID, 5)), anydtdtm32.);
SIZE =input(finfo(FID, foptname(FID, 4)), 32.);
FID =fclose(FID);
end;
end;
else do;
DNAME=catx(SEP, DNAME, FILENAME);
FILENAME=' ';
end;
replace;
if DIR;
LEVEL=LEVEL+1;
do I=1 to dnum(RC2);
FILENAME=dread(RC2, I);
output;
end;
RC3=dclose(RC2);
run;
You need to use DOPEN() , DREAD(), FILEINFO() etc to read the filesize for each file. Look in the SAS on line manual for those statements and there should be examples.
If you need to recurse into sub directories then it might be a little complicated.
@Tom wrote:
If you need to recurse into sub directories then it might be a little complicated.
See my answer. Since macros can be used recursively, they are the tool of choice here IMO.
But compared to using a simple du -sk, the code is ridiculous. I cannot (and will never) fathom the reasons for NOXCMD.
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 25. 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.