@ScottBass wrote:However, now I'll hijack your post 😉 (temporarily)...
I often like a "pure macro" solution when possible (or if it makes sense). So, does anyone know why the first delete files macro fails? I know it's due to the fexist function, I just don't see why it's returning 0 instead of 1? The second data step macro works, and does delete the CSV files.
I've found the answer:
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000210817.htm
If you look very closely at the example (which doesn't make clear that &fref isn't an already existing macro variable):
%if %sysfunc(fexist(&fref)) %then %put The file identified by the fileref &fref exists.; %else %put %sysfunc(sysmsg());
Changing this to open code:
%let rc=%sysfunc(filename(foo,G:\SAS\Work\_TD7752_MYSERVERNAME_\Prc2\class01.csv));
%put &=rc;
%let rc=%sysfunc(fexist(foo)); * fails ;
%put &=rc;
%let rc=%sysfunc(fexist(&foo)); * works ;
%put &=rc;
So, macro variable &foo does not exist, yes that's the syntax required for the fexist function (when called via %sysfunc)???
What genius came up with this syntax? Or am I missing something?
If you make this change to my previous code, the "all macro" version of %code works and deletes the CSV files:
* delete the CSVs ;
%macro code;
%let fullname=%sysfunc(strip(&fullname));
%let rc=%sysfunc(filename(________,&fullname));
%if (&rc eq 0 and %sysfunc(fexist(&________)) eq 1) %then %do;
%let rc=%sysfunc(fdelete(&________));
%if (&rc eq 0) %then
%put &fullname deleted.;
%else
%put &fullname was not deleted.;
%end;
%let rc=%sysfunc(filename(________));
%mend;
%loop_control(control=dirlist)
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000245893.htm (fdelete - no macro example in the doc. fdelete also needs the bogus ampersand.)
I checked to see if the 9.4 documentation was updated:
The "example" makes no sense.
No examples at all. Seems like the documentation is regressing!
Huh?
The FEXIST() function takes as input the FILEREF of the file to be tested. You can just type the fileref or put the fileref into a macro variable and expand the macro variable.
If you try to reference a macro variable that doesn't exist then you will pass the FEXIST() a string with an & in it, which is an impossible value for a FILEREF.
@Tom wrote:
Huh?
The FEXIST() function takes as input the FILEREF of the file to be tested. You can just type the fileref or put the fileref into a macro variable and expand the macro variable.
If you try to reference a macro variable that doesn't exist then you will pass the FEXIST() a string with an & in it, which is an impossible value for a FILEREF.
Hi @Tom,
Yeah, I said "Huh?" myself, but not for the same reason as you.
Run the code I posted. It's self-contained, you can just paste it into SAS.
Edit: Actually, not really, you'll need some macros from https://github.com/scottbass/SAS/tree/master/Macro.
The fileref I used was 8 underscores, which more than likely won't clobber an existing fileref.
The code only works properly when I specify &________ for fexist and fdelete. That macro variable does not exist.
BTW, SAS 9.3 on Windows.
Perhaps the issue is somewhere else in the code?
This works fine with a fileref of 8 underscores.
%let fileref=________;
filename &fileref temp;
%put Does &fileref exist? %sysfunc(fexist(&fileref)) ;
%put Does ________ exist? %sysfunc(fexist(________)) ;
data _null_;
file ________;
put 'Hello';
run;
%put Does &fileref exist? %sysfunc(fexist(&fileref)) ;
%put Does ________ exist? %sysfunc(fexist(________)) ;
* create file ;
filename foo "%sysfunc(pathname(work))\foo.csv";
data _null_;
file foo;
put 'blah blah blah';;
run;
filename foo;
* delete file using macro code ;
%let rc=%sysfunc(filename(________,%sysfunc(pathname(work))\foo.csv)); * works ;
%put &=rc;
%let exists=%sysfunc(fexist(________)); * fails, returns 0 not 1 ;
%put &=exists;
%let rc=%sysfunc(fdelete(________)); * fails, does not delete file ; ;
%put &=rc;
%let exists=%sysfunc(fexist(&________)); * works, returns 1, even though macro variable &foo does not exist ;
%put &=exists;
%let rc=%sysfunc(fdelete(&________)); * works, deletes file ;
%put &=rc;
%let rc=%sysfunc(filename(________));
%put &=rc;
And my SAS log:
27 * create file ;
28 filename foo "%sysfunc(pathname(work))\foo.csv";
29 data _null_;
30 file foo;
31 put 'blah blah blah';;
32 run;
NOTE: The file FOO is:
Filename=G:\SAS\Work\_TD8076_XXXXXXXX_\Prc2\foo.csv,
RECFM=V,LRECL=256,File Size (bytes)=0,
Last Modified=24 July 2019 11:49:24,
Create Time=24 July 2019 11:49:24
NOTE: 1 record was written to the file FOO.
The minimum record length was 14.
The maximum record length was 14.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
33 filename foo;
NOTE: Fileref FOO has been deassigned.
34
35 * delete file using macro code ;
36 %let rc=%sysfunc(filename(________,%sysfunc(pathname(work))\foo.csv)); * works ;
37 %put &=rc;
RC=0
38
39 %let exists=%sysfunc(fexist(________)); * fails, returns 0 not 1 ;
40 %put &=exists;
EXISTS=0
41 %let rc=%sysfunc(fdelete(________)); * fails, does not delete file ; ;
42 %put &=rc;
RC=20004
43
44 %let exists=%sysfunc(fexist(&________)); * works, returns 1, even though macro variable &________ does not exist ;
45 %put &=exists;
EXISTS=1
46 %let rc=%sysfunc(fdelete(&________)); * works, deletes file, even though macro variable &________ does not exist ;
47 %put &=rc;
RC=0
48
49 %let rc=%sysfunc(filename(________));
50 %put &=rc;
RC=0
I admit it's weird, and perhaps I'm missing something, but I don't get it...
You told FILENAME() to use the MACRO VARIABLE named ________.
@Tom wrote:
You told FILENAME() to use the MACRO VARIABLE named ________.
Which did not exist (I started a fresh SAS session), yet "worked" (no unresolved macro variable warning), THEN created &________ (AFAIK undocumented behaviour).
Anyway, I didn't mean to hijack @kmardinian post. PM me to discuss further 😉
The FILENAME() function is probably your issue.
specifies the fileref to assign to the external file. In a DATA step, fileref can be a character expression, a string enclosed in single quotation marks that specifies the fileref, or a DATA step variable whose value contains the fileref. In a macro (for example, in the %SYSFUNC function), fileref is the name of a macro variable (without an ampersand) whose value contains the fileref to assign to the external file. If the function is used within a DATA step, the fileref must be enclosed in single quotation marks. If the function is used in macro code, the fileref must not be enclosed in quotation marks.
If you want to use the FILENAME() function to create filref of FRED the set a macro variable to the value FRED and pass the NAME of the macro to FILENAME() function.
%let fileref=________;
%let rc1=%sysfunc(filename(fileref,"my physical file"));
%let rc2=%sysfunc(fexist(&fileref));
Or leave the macro variable empty and the FILENAME() function will make up a fileref name for you.
704 %let fileref=; 705 %let rc=%sysfunc(filename(fileref,"C:\download\does no exist")); 706 %put &=fileref Does it Exist? %sysfunc(fexist(&fileref)) ; FILEREF=#LN00196 Does it Exist? 0
Thanks.
I still contend that SAS R&D could have made the syntax better when invoking filename/fexist/fdelete via %sysfunc.
Why do I need to create a macro variable for the fileref parameter to filename, instead of just entering the text that the macro variable would contain (like everywhere else in SAS)?
Perhaps if I don't specify a macro variable as the parameter to the filename function(contrary to the documentation, as you pointed out), the filename function creates &________?
I still contend poor syntax and poor documentation, but thanks for clarifying.
Edit: Yeah, see here. Again, the doc could be clearer:
* create file ;
filename foo "%sysfunc(pathname(work))\foo.csv";
data _null_;
file foo;
put 'blah blah blah';;
run;
filename foo;
* delete file using macro code ;
%let rc=%sysfunc(filename(________,%sysfunc(pathname(work))\foo.csv)); * works ;
%put &=rc;
%put &=________; * <<<<<<<<<< ;
%let exists=%sysfunc(fexist(________)); * fails, returns 0 not 1 ;
%put &=exists;
%let rc=%sysfunc(fdelete(________)); * fails, does not delete file ; ;
%put &=rc;
%let exists=%sysfunc(fexist(&________)); * works, returns 1, even though macro variable &foo does not exist ;
%put &=exists;
%let rc=%sysfunc(fdelete(&________)); * works, deletes file ;
%put &=rc;
%let rc=%sysfunc(filename(________));
%put &=rc;
In a macro (for example, in the %SYSFUNC function), fileref is the name of a macro variable (without an ampersand) whose value contains the fileref to assign to the external file.
I think that's why @ScottBass got his knickers in a twist.
There are very few cases where one can access the value of a macro variable without using ampersand. I can think of symget() and %superq().
Why the filename() function was implemented this way seems atypical indeed.
It's probably so that "discardable" names such as #LN00196 can be created transparently, in a manner similar to the TEMP device, as shown in the common examples of this function being used in the macro language:
%let fileref=; %let rc=%sysfunc(filename(fileref,&path));
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.