Hi,
I have the code below (partial code) to extract files from zipfiles. As you can see I only keep the zipfile name and the contents of the zipfile. However I would like to have file properties of the individual zip file files such as Last Update, Date Creation, Author, File Size.
What would I add to the code below to achieve that ?
Many thanks !
%do i = 1 %to &zipcount;
filename targzip ZIP "%bquote(%superq(targdir)/%superq(zname&i))";
data _contents&i.(keep=zip memname);
length zip $200 memname $200;
zip="%bquote(%superq(targdir)/%superq(zname&i))";
fid=dopen("targzip");
if fid=0 then
stop;
memcount=dnum(fid);
do i=1 to memcount;
memname=dread(fid,i);
if (first(reverse(trim(memname))) ^='/') then
output;
end;
rc=dclose(fid);
run;
filename targzip clear;
%end;
The FINFO support was added in SAS 9.4 Maint 3. Run:
proc product_status; run;
To make sure you're at that level or higher.
Sample output:
For Base SAS Software ... Custom version information: 9.4_M5 Image version information: 9.04.01M5P090617 For SAS/STAT ... Custom version information: 14.3 For SAS/GRAPH ... Custom version information: 9.4_M5
What you are asking for is system information, i.e. from the command line. This information really isn't useful in any real way, dates and such like can be easily incorrect or manipulated. What is it your actually trying to do, as it seems to be circling one main issue. What I suspect is you have a load of ZIP files and you are trying to process them all and document the process. If you don't need the contents, what is it you actually need?
As for your question, two options, extract all to folder, then do a dir list of that folder to get those properties. Or get a tool like 7Zip and call that from the command line to return items from the zip:
https://sevenzip.osdn.jp/chm/cmdline/commands/list.htm
Until I know what it is your doing its hard to provide any kind of useful solution.
I think you can use the MOPEN and then the FINFO function to get available data about each member, e.g.:
memname=dread(fid,i);
if first(reverse(trim(memname)))^='/' then do;
mid=mopen(fid,memname);
Create_time=finfo(mid,'Create Time');
output;
rc=fclose(mid);
end;
See the documentation, and the examples there, for information about which information items are available. The "Author" is not available here, nor is it otherwise available for all file types under the Windows platform, I think this property is saved inside the file for e.g. Office files.
Hi,
This sounds logical. For some reason i still can't get the syntax right. What is wrong below ?
filename targzip ZIP "%bquote(%superq(targdir)/%superq(zname&i))";
data _contents&i.(keep=zip memname create_time);
length zip $200 memname $200;
zip="%bquote(%superq(targdir)/%superq(zname&i))";
fid=dopen("targzip");
if fid=0 then
stop;
memcount=dnum(fid);
do i=1 to memcount;
memname=dread(fid,i);
if (first(reverse(trim(memname))) ^='/') then do;
mid=mopen(fid,memname);
Create_time=finfo(mid,'Create Time');
output;
rc=fclose(mid);
end;
rc=dclose(fid);
end;
run;
filename targzip clear;
Thanks !
Rgds
B
I have an example of how to accomplish this here:
Using FILENAME ZIP and FINFO to list details from your ZIP files
A complete SAS macro that you can use is in my GitHub gist.
Hi Chris,
Thanks very much for the link. I would like to see the example.
I clicked on it but unfortunately it does not work.
Rgds
B
Hi Chris,
Sorry for my previous message and the confusieon. The link does work. However my company's security policy prevents me from downloading your code.
Just was able to open it on my mobile 😉
Thanks for your explanation on this supported with code !
Rgds
B
A company blocking GitHub seems like a really bad decision, especially for developers.
Here's a copy of Chris's code.
/* Produce a list of ZIP files and their entries from a single folder */
%macro listzipcontents (
targdir= /* a system folder that contains ZIP files */,
outlist= /* output data set for list of files and members */);
filename targdir "&targdir";
/* Gather all ZIP files in a given folder */
/* Searches just one folder, not subfolders */
/* for a fancier example see */
/* http://support.sas.com/kb/45/805.html (Full Code tab) */
data _zipfiles;
length fid 8;
fid=dopen('targdir');
if fid=0 then
stop;
memcount=dnum(fid);
/* Find all ZIP files. GZ files added in 9.4 Maint 5 */
do i=1 to memcount;
memname=dread(fid,i);
if lowcase( scan( memname,-1,'.') in ('zip')) then
output;
end;
rc=dclose(fid);
run;
filename targdir clear;
/* get the memnames into macro vars */
proc sql noprint;
select memname into: zname1- from _zipfiles;
%let zipcount=&sqlobs;
quit;
/* for all ZIP files, gather the members */
%do i = 1 %to &zipcount;
%put &targdir/&&zname&i;
filename targzip ZIP "&targdir/&&zname&i";
data _contents&i.(keep=zip memname);
length zip $200 memname $200 ;
zip="&targdir/&&zname&i";
fid=dopen("targzip");
if fid=0 then
stop;
memcount=dnum(fid);
do i=1 to memcount;
memname=dread(fid,i);
/* save only full file names, not directory names */
if (first(reverse(trim(memname))) ^='/') then
output;
end;
rc=dclose(fid);
run;
filename targzip clear;
%end;
/* Combine the member names into a single data set */
/* the colon notation matches all files with "_contents" prefix */
data &outlist.;
set _contents:;
run;
/* cleanup temp files */
proc datasets lib=work nodetails nolist;
delete _contents:;
delete _zipfiles;
run;
%mend;
/* Build the file details for a single ZIP member */
%macro getzipmemberinfo(
f /* fileref of a ZIP/member= combination */,
out /* output data set for details of just this ZIP member */);
data &out.;
length filename $ 200
membername $ 200
filetime 8
filesize 8
compressedsize 8
compressedratio 8
CRC32 $ 8;
keep filename
membername
filetime
filesize
compressedsize
compressedratio
CRC32;
format filetime datetime20.
filesize sizekmg10.2
compressedsize sizekmg10.2
compressedratio percent6.;
/* These FINFO attributes are specific to ZIP file members */
fId = fopen("&f","S");
if fID then
do;
infonum=foptnum(fid);
do i=1 to infonum;
infoname=foptname(fid,i);
select (infoname);
when ('Filename') filename=finfo(fid,infoname);
when ('Member Name') membername=finfo(fid,infoname);
when ('Size') filesize=input(finfo(fid,infoname),15.);
when ('Compressed Size') compressedsize=input(finfo(fid,infoname),15.);
when ('CRC-32') crc32=finfo(fid,infoname);
when ('Date/Time') filetime=input(finfo(fid,infoname),anydtdtm.);
end;
end;
compressedratio = compressedsize / filesize;
output;
fId = fClose( fId );
end;
run;
%mend;
/* Given a data set of ZIP file names and entries, assemble the member details */
/* Assumes input contains 'zip' and 'memname' columns, as produced by */
/* the %listzipcontents() macro. */
%macro getZipDetails(
inlist= /* two-column data set with zip (full path of ZIP file) and memname (entry in ZIP file) */,
outlist= /* data set for output details */);
/* Build a list of FILENAME statements */
proc sql noprint;
select cat('FILENAME f ZIP "',trim(zip),'" member="',trim(memname),'";') length=300
into: fnames1- from &inlist.;
%let fcount=&sqlobs.;
quit;
/* One by one, assign the fileref to a ZIP member, fetch details, clear fileref */
%do i = 1 %to &fcount;
&&fnames&i.;
%getzipmemberinfo(f,_deets&i.);
filename f clear;
%end;
/* aggegate results into a single output */
data &outlist.;
set _deets:;
run;
/* Clean up temp files */
proc datasets lib=work nodetails nolist;
delete _deets:;
quit;
%mend;
/* To use: first run LISTZIPCONTENTS with folder that contains */
/* ZIP files you want details for, then run GETZIPDETAILS on the */
/* output of that. */
/* Output: a SAS data set with zip member details. */
/*
filename membername filetime filesize compressedsize compressedratio CRC32
SAS.MacroViewer.zip SAS.MacroViewer.dll 29SEP2012:09:49:18 139.00KB 51.32KB 37% 054AEBC6
SASPress.CustomTasks.DS2Datalines_src.zip src/Properties/AssemblyInfo.cs 27NOV2012:20:57:06 1.11KB 0.51KB 46% FAC88DED
SASPress.Facebook_src.zip src/FacebookConnector/Properties/AssemblyInfo.cs 16JAN2011:12:06:24 1.43KB 0.63KB 44% 2C86F829
SASPress.Facebook_src.zip src/FacebookConnector/Properties/Resources.Designer.cs 21JAN2011:20:04:54 2.78KB 0.90KB 32% C7508420
SASPress.Facebook_src.zip src/FacebookConnector/Properties/Resources.resx 21JAN2011:20:04:54 5.82KB 1.48KB 25% E0C8C87E
SASPress.Facebook_src.zip src/FacebookConnector/Properties/Settings.Designer.cs 19JAN2011:08:28:06 1.07KB 0.45KB 42% 4DDC113E
SASPress.Facebook_src.zip src/FacebookConnector/Properties/Settings.settings 16JAN2011:12:06:24 0.24KB 0.17KB 70% 12D89760
SASPress.Facebook_src.zip src/FacebookConnector/README.txt 23JAN2011:13:12:38 5.12KB 2.08KB 41% 19CEF39C
SASPress.Facebook_src.zip src/README.txt 23JAN2011:13:12:38 5.12KB 2.08KB 41% 19CEF39C
*/
/* Sample use:
%listzipcontents (targdir=C:\Projects\ZIPPED_Examples, outlist=work.zipfiles);
%getZipDetails (inlist=work.zipfiles, outlist=work.zipdetails);
*/
Thanks Reeza !
I'm running this but unfortunately i do not get the file properties. I do get the properties :
filename | membername | filetime | filesize | compressedsize | compressedratio | CRC32 |
g:\folder1\folder2\test1.zip | TESTFILE1.TXT | . | . | . | . | . |
g:\folder1\folder2\test2.zip | TESFILE2.TXT | . | . | . | . | . |
This is my macro call :
%listzipcontents (targdir=g:\folder1\folder2\20171230, outlist=work.zipfiles);
%getZipDetails (inlist=work.zipfiles, outlist=work.zipdetails);
What could go wrong ?
I copied the exact contents of the macros...
Thanks
B
Sorry I meant :
%listzipcontents (targdir=g:\folder1\folder2, outlist=work.zipfiles);
%getZipDetails (inlist=work.zipfiles, outlist=work.zipdetails);
The FINFO support was added in SAS 9.4 Maint 3. Run:
proc product_status; run;
To make sure you're at that level or higher.
Sample output:
For Base SAS Software ... Custom version information: 9.4_M5 Image version information: 9.04.01M5P090617 For SAS/STAT ... Custom version information: 14.3 For SAS/GRAPH ... Custom version information: 9.4_M5
Hi Chris,
Thanks for sharing this.
It appears we have M1.
For Base SAS Software ...
Custom version information: 9.4_M1
Image version information: 9.04.01M1P120413
It's a huge relief. For a moment I really thought I would go crazy 😉
Is there another way to get file details from files within zip files ?
Thanks again !
Rgds
B
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.