I am trying to put a bunch of code I found online together to get it to make a copy of a log file and put it somewhere else before it deletes it BUT ONLY when a directory is running out of space.
I am able to get it to do most of that BUT... I can't get it to copy with a reference to a sas variable... I can get it to do it if I hard code the file name (make a copy that is) but having a hard time with filename specifically...
This is the line I am struggling with:
filename src "&loglocation!!\!!memname" recfm=n ;
THIS IS THE REST OF IT...
I'm not using the destination reference yet because it's the same problem really... It probably needs a lot of work for other issues as well but for now I just don't know how to get it to take a reference to a sas variable to get the file that it is ON in the loop to MAKE THE COPY...
%macro mr_clean(loglocation=, destpathcopy=);
data temporary;
length memname $256;
/*Today's date minus 30 days is the date before which we delete*/
deldate = today() - 0;
/*filename assigns a file reference to and external file, indir becomes external file */
rc = filename('indir',"&loglocation");
/*Obtain directory number from indir to use with other functions*/
did = dopen('indir');
/*If it exists then do the following until the total number of files in directory*/
if did then
do i=1 to dnum(did);
/*Select the i'th file in the directory and give the NAME of the directory member */
memname = dread(did,i);
output;
/*From the end of the file if it's .log then continue*/
if reverse(trim(memname))=: reverse('gol.') then continue;
/*GIve another file reference but to the full path with the member*/
rc =filename('inmem',"&loglocation/"!!memname);
/*Give the file a number*/
fid = fopen('inmem');
output;
if fid then do;
tmp1 = finfo(fid,'Last Modified');
output;
if scan(tmp1,1)='January' then month='01';
else if scan(tmp1,1)='February' then month='02';
else if scan(tmp1,1)='March' then month='03';
else if scan(tmp1,1)='April' then month='04';
else if scan(tmp1,1)='May' then month='05';
else if scan(tmp1,1)='June' then month='06';
else if scan(tmp1,1)='July' then month='07';
else if scan(tmp1,1)='August' then month='08';
else if scan(tmp1,1)='September' then month='09';
else if scan(tmp1,1)='October' then month='10';
else if scan(tmp1,1)='November' then month='11';
else if scan(tmp1,1)='December' then month='12';
else month ='missing';
output;
tmp2=month||'/'||scan(tmp1,2)||'/'||scan(tmp1,3);
output;
moddate = input(tmp2, MMDDYY10.);
output;
rc = fclose(fid);
if . < moddate <= deldate then do;
filename src "&loglocation!!\!!memname" recfm=n ;
filename dst "E:\Logs_copy\SASPrincipalServices9.4.log" /*recfm=n*/;
%let rc1 = %sysfunc(FCOPY(src,dst));
%put %sysfunc(SYSMSG());
rc = fdelete("inmem");
end;
end;
end;
rc = dclose(did);
rc = filename('inmem');
rc = filename('indir');
run;
%mend;
%macro windows_bytes_free(sm_path=/*, ds_path=*/);
%global mv_bytes_free;
%let mv_bytes_free = -1; /* In case of error */
%let filepath = %sysfunc(quote(%qsysfunc(dequote(&sm_path)))); /* To prevent issues with quotes remove quotes if present and apply it again*/
/* Run the DIR command and retrieve results using an unnamed pipe */
filename tempdir pipe %sysfunc(quote(dir /-c &filepath | find "bytes free")) ;
data _null_;
infile tempdir length=reclen ;
input line $varying1024. reclen ;
re = prxparse('/([0-9]+) bytes/'); /* Parse the output of DIR using a Perl regular expression */
if prxmatch(re, line) then do;
bytes_str = prxposn(re, 1, line);
bytes = input(bytes_str, 20.);
call symput('mv_bytes_free', bytes); /* Assign available disk space in bytes to a global macro variable */
kb = bytes /1024;
mb = kb / 1024;
gb = mb / 1024;
format bytes comma20.0;
format kb mb gb comma20.1;
/* Write a note to the SAS log */
put "NOTE: &sm_path " bytes= kb= mb= gb=;
if gb>5 then call execute('%mr_clean(loglocation=&sm_path);');
/*put '** Available space is less than 5 gb';*/
else put '** Enough space is available';
end;
run;
%if &mv_bytes_free eq -1 %then %put ERROR: error in windows_bytes_free macro;
%mend;
%windows_bytes_free(sm_path=D:\SAS\Config\Lev1\Web\Logs\SASServer1_1\Logs_Copy/* ds_path=E:\Logs_copy*/);
This is the error message I am currently getting
NOTE: D:\SAS\Config\Lev1\Web\Logs\SASServer1_1\Logs_Copy bytes=33,067,778,048 kb=32,292,752.0
mb=31,535.9 gb=30.8
ERROR: Physical file does not exist, D:\SAS\Config\Lev1\Web\Logs\SASServer1_1\Logs_Copy!!\!!memname.
NOTE: 1 record was read from the infile TEMPDIR.
The minimum record length was 50.
The maximum record length was 50.
NOTE: DATA statement used (Total process time):
real time 0.04 seconds
cpu time 0.01 seconds
Why aren't you using the FILENAME function instead of the statement as you've done elsewhere in your DATA step? The FILENAME function will work as you intend.
I was under the impression that this would give it a file reference which I thought was just a number rather than the name and the fcopy I believe just needs a filepath.
rc =filename('inmem',"&loglocation/"!!memname);
What do you think?
I tried this too.. It still says it can't find the file. It doesn't resolve memname for some reason. I used dread to get the memname but I don't see why it wouldn't just resolve memname. I don't get it and I feel like I've tried so many options.
src=filename("&loglocation/"!!memname);
FCOPY copies from one fileref to another: https://documentation.sas.com/?docsetId=lefunctionsref&docsetTarget=n10dz22b5ixohin1vwzilweetek0.htm...
So using it with the FILENAME function is the way to go.
Use FILENAME as you did originally and it should work:
rc =filename('inmem',"&loglocation/"!!memname);
src resolves to 20014 a number when I do that. Perhaps I don't understand the function as well as you do:)
FCOPY requires a fileref which in your case is INMEM. SRC is just the return code off the FILENAME function. You can only use it to check if the function worked OK, nothing else.
Like this?
rc = fcopy('INMEM','OUTMEM');
I tried it.
rc = fcopy('INMEM','OUTMEM');
Still doesn't work for me. The only way I can actually get it to make the copy of the file is with this.. This works but I want it to go through the directory and select the files that meet criteria.
if . < moddate <= deldate then do;
filename src "D:\SAS\Config\Lev1\Web\Logs\SASServer1_1\Logs_Copy\SASPrincipalServices9.4.log" /*recfm=n*/;
filename dst "E:\Logs_Copy\SASPrincipalServices9.4.log" /*recfm=n*/;
%let rc1 = %sysfunc(FCOPY(src,dst));
I'll post if I find the solution or please let me know if you have other ideas.
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.