I am dealing with some files that need to be FDELETED after they are used. However, I only get a log message:
ERROR: Invalid physical name.
I've discovered I can used brackets in some scenarios by using backslash (\[)...\]) to apparently escape the [ which causes the above error.
I recall reading some SAS documentation that [] in filename is used like a regex character class, but I can't find that doc again -- it might have been Viya related, but I am not using Viya.
Example:
%let workpath = %sysfunc(pathname(WORK)) ;
%let testpath = &workpath/test ;
options dlcreatedir ;
libname testpath "&testpath" ;
options nodlcreatedir ;
* Create a test file whose name contains brackets ;
filename bracket "&testpath/ABC_\[123\]_DEF.txt" ;
ata _null_;
file bracket;
put 'Where do you want these shelves?';
run ;
* Process the test file ;
data _null_ ;
infile bracket ;
input; put _infile_;
run;
* List the files in test folder and try to delete them with FDELETE ;
data _null_ ;
length dref fref $8 fname $256 msg $200 ;
rc = filename (dref, "&testpath") ;
did = dopen(dref); msg=sysmsg() ;
do i = 1 to dnum(did) ;
fname = dread(did, i) ;
put 'NOTE: ' i fname ;
rc = filename (fref, cats("&testpath",'/',fname)) ; msg = sysmsg() ; put 'NOTE: filename() ' rc= fname= / msg ;
rc = FDELETE(fref) ; msg = sysmsg() ; put 'NOTE: fdelete() ' rc= / msg ;
if index(fname,'[') then do ;
fname = transtrn(fname,'[','\[') ; * try to escape the brackets ;
fname = transtrn(fname,']','\]') ;
rc = filename (fref, cats("&testpath",'/',fname)) ; msg = sysmsg() ; put 'NOTE: filename() ' rc= fname= / msg ;
rc = FDELETE(fref) ; msg = sysmsg() ; put 'NOTE: fdelete() ' rc= / msg ;
end ;
rc = filename (fref) ;
end ;
run ;
* try delete the escaped filename referenced by bracket;
%put NOTE: FDELETE rc=%sysfunc(fdelete(bracket)) ;
%put %sysfunc(sysmsg()) ;
will log the ERROR: for each way I try to FDELETE
225 %let workpath = %sysfunc(pathname(WORK)) ;
226 %let testpath = &workpath/test ;
227
228 options dlcreatedir ;
229 libname testpath "&testpath" ;
NOTE: Libref TESTPATH was successfully assigned as follows:
Engine: V9
Physical Name: /saswork/sas_tmp/SAS_work##########/SAS_work##########/test
230 options nodlcreatedir ;
231
232 filename bracket "&testpath/ABC_\[123\]_DEF.txt" ;
233
234 data _null_;
235 file bracket;
236 put 'Where do you want these shelves?';
237 run ;
NOTE: The file BRACKET is:
Filename=/saswork/sas_tmp/SAS_work##########/SAS_work##########/test/ABC_\[123\]_DEF.txt,
Owner Name=########,Group Name=########,
Access Permission=-rw-rw-rw-,
Last Modified=17Jul2025:08:27:44
NOTE: 1 record was written to the file BRACKET.
The minimum record length was 32.
The maximum record length was 32.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
238
239 data _null_ ;
240 infile bracket ;
241 input; put _infile_;
242 run;
NOTE: The infile BRACKET is:
Filename=/saswork/sas_tmp/SAS_work##########/SAS_work##########/test/ABC_\[123\]_DEF.txt,
Owner Name=########,Group Name=########,
Access Permission=-rw-rw-rw-,
Last Modified=17Jul2025:08:27:44,
File Size (bytes)=33
Where do you want these shelves?
NOTE: 1 record was read from the infile BRACKET.
The minimum record length was 32.
The maximum record length was 32.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
243
244 * List the files in test folder and try to delete them ;
245
246 data _null_ ;
247 length dref fref $8 fname $256 msg $200 ;
248 rc = filename (dref, "&testpath") ;
249 did = dopen(dref); msg=sysmsg() ;
250 do i = 1 to dnum(did) ;
251 fname = dread(did, i) ;
252 put 'NOTE: ' i fname ;
253 rc = filename (fref, cats("&testpath",'/',fname)) ; msg = sysmsg() ; put 'NOTE: filename() ' rc= fname= / msg ;
254 rc = FDELETE(fref) ; msg = sysmsg() ; put 'NOTE: fdelete() ' rc= / msg ;
255 if index(fname,'[') then do ;
256 fname = transtrn(fname,'[','\[') ;
257 fname = transtrn(fname,']','\]') ;
258 rc = filename (fref, cats("&testpath",'/',fname)) ; msg = sysmsg() ; put 'NOTE: filename() ' rc= fname= / msg ;
259 rc = FDELETE(fref) ; msg = sysmsg() ; put 'NOTE: fdelete() ' rc= / msg ;
260 end ;
261 rc = filename (fref) ;
262 end ;
263 run ;
NOTE: 1 ABC_[123]_DEF.txt
NOTE: filename() rc=0 fname=ABC_[123]_DEF.txt
NOTE: fdelete() rc=20017
ERROR: Invalid physical name.
NOTE: filename() rc=0 fname=ABC_\[123\]_DEF.txt
NOTE: fdelete() rc=20017
ERROR: Invalid physical name.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
264
265 * try delete the escaped filename referenced by bracket;
266
267 %put NOTE: macro FDELETE rc=%sysfunc(fdelete(bracket)) ;
NOTE: macro FDELETE rc=20017
268 %put %sysfunc(sysmsg()) ;
ERROR: Invalid physical name.
I would raise that as an issue with SAS support.
Square brackets should not cause any trouble in SAS code and I am pretty sure they did not in the past. But at the very least FDELETE() should handle the same way as normal writing and reading operations do.
I have definitely had the opposite problem in the past. SAS would allow you to make filenames that are difficult to work with from Unix prompt. Names with spaces or * in them.
If you do have XCMD option enabled you can use the Unix command rm to delete the file.
data _null_;
cmd=catx(' ','rm',pathname('bracket'));
infile dummy pipe filevar=cmd;
input;
put _infile_;
run;
PS You might need use \rm instead of rm as the command. This will force it use the rm command directly instead of any alias that might have been defined. to avoid complication from Unix shops that have defined aliases for rm to force it to prompt before removing a file.
Hi @RichardAD
I won't help you with a solution, unfortunately, but I have some more observations.
1) It looks like it it's not only FDELETE() have problems with [].
My idea was "let's try rename and the delete", so I did a small test for RENAME() with 6 different approaches, but it returned the same error, log below.
1 %put %sysfunc(rename(&testpath./ABC_\[123\]_DEF.txt, &testpath./ABC_123_DEF.txt, file));
1
2 %put %sysfunc(sysmsg()) ;
ERROR: Invalid physical name.
3
4 %put %sysfunc(rename("&testpath./ABC_[123]_DEF.txt", &testpath./ABC_123_DEF.txt, file));
1
5 %put %sysfunc(sysmsg()) ;
ERROR: Invalid physical name.
6
7 %put %sysfunc(rename('&testpath./ABC_[123]_DEF.txt', &testpath./ABC_123_DEF.txt, file));
1
8 %put %sysfunc(sysmsg()) ;
ERROR: Invalid physical name.
9
10 %put %sysfunc(rename(%str(&testpath./ABC_\[123\]_DEF.txt), &testpath./ABC_123_DEF.txt, file));
1
11 %put %sysfunc(sysmsg()) ;
ERROR: Invalid physical name.
12
13 %put %sysfunc(rename("&testpath./ABC_\[123\]_DEF.txt", &testpath./ABC_123_DEF.txt, file));
1
14 %put %sysfunc(sysmsg()) ;
ERROR: Invalid physical name.
15
16 %put %sysfunc(rename('&testpath./ABC_\[123\]_DEF.txt', &testpath./ABC_123_DEF.txt, file));
1
17 %put %sysfunc(sysmsg()) ;
ERROR: Invalid physical name.
2) Furthermore, when I tried delete "ABC_[123]_DEF.txt
" in SAS Studio I also got an error.
3) Another "fun fact" is that when I created a directory with [], Linux tree command on OS level shows:
.
├── ABC_[123]_DEF.txt
├── DEF_[123]_DEF.txt
├── GHI_[123]_DEF.txt
└── test[123]
├── test[123]next.txt
└── test.txt
1 directory, 5 files
but SAS Studio does not see that sub-directory at all:
Last 2 things. If you happen to have XCMD on, maybe you could use filename PIPE to run;
rm '/path/to/file/ABC_[123]_DEF.txt';
on the OS level, with filename surrounded by quotes.
Or, in the BasePlus package there is the %bpPIPE() macro that may be useful:
%bpPIPE(rm "&testpath./ABC_[123]_DEF.txt")
All the best
Bart
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
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.