Not sure how complex macro code makes things readable, but you can certainly use %NRSTR() to protect & characters. You just need to remember not to unquote them before you can protect them with actual quotes.
You can use the actual QUOTE() function to add single quotes around the string.
63 %let file1="%sysget(USERPROFILE)\Desktop\%nrstr(S&P) 500_%sysfunc(today(),yymmddn6).xlsx";
64 %let file2="%nrstr(S&P) 500_%sysfunc(putn(%sysfunc(today())+1,yymmddn6.)).xlsx";
65
66 data _null_;
67 infile %sysfunc(quote(ren &file1 &file2,%str(%'))) pipe;
68 input;
69 put _infile_;
70 run;
NOTE: The infile 'ren "C:\Users\xxx\Desktop\S&P 500_230329.xlsx" "S&P 500_230330.xlsx"' is:
Unnamed Pipe Access Device,
PROCESS=ren "C:\Users\xxx\Desktop\S&P 500_230329.xlsx" "S&P 500_230330.xlsx",
RECFM=V,LRECL=32767
Stderr output:
The system cannot find the file specified.
NOTE: 0 records were read from the infile 'ren "C:\Users\xxx\Desktop\S&P 500_230329.xlsx" "S&P 500_230330.xlsx"'.
NOTE: DATA statement used (Total process time):
real time 0.07 seconds
cpu time 0.00 seconds
Or if you know that the string does not contain any single quotes you can use %BQUOTE() to get the single quotes, but you will need to use %unquote() to remove the macro quoting so that SAS can see that you actually passed a quoted string to the INFILE statement.
data _null_;
infile %unquote(%bquote('ren &file1 &file2')) pipe;
input;
put _infile_;
run;
... View more