I would like to delete the folder folderToDelete, which contains subfolders and those folders might contain subfolders, and so on.
I do not have permission to do the x command.
I have the following code (after looking at the following post Delete folder (directory) and all files in it😞
%macro delete_folder(folderToDelete);
data work.FilesToDelete;
length Name $ 100;
keep Name;
rc = filename("folder", "&folderToDelete.");
dirId = dopen("folder");
do i = 1 to dnum(dirID);
Name = dread(dirId, i);
output;
end;
rc = dclose(dirId);
run;
data _null_;
set work.FilesToDelete end=lastDeleted;
put "Deleting " Name;
rc = filename("delfile", cats("&folderToDelete./", Name));
rc = fdelete("delfile");
put "del file " rc=;
rc = filename("delfile");
if lastDeleted then do;
put "Deleting the folder '&folderToDelete.'";
rc = filename("folder", "&folderToDelete.");
rc = fdelete("folder");
put "del folder " rc=;
rc = filename("folder");
end;
run;
%mend;
However, since my folder contains subfolders, only the tables are delete and not the subfolders, resulting in the main folder not being deleted. In that sense, what I would like was to apply a function recursively to delete every file inside any subfolder (or any other suggestion you might have).
As an example, if my folder has the following structure:
> folder
> subfolder_1
> T_1_1.sas7bdat
> T_1_2.sas7bdat
> T_1_3.sas7bdat
> subsubfolder_1
> T_1_1_1.sas7bdat
> subfolder_2
> T_2_1.sas7bdat
> T_1.sas7bdat
> T_2.sas7bdat
> T_3.sas7bdat
> T_4.sas7bdat
after running the first data step, which reads the folder, I get
Name |
subfolder_1 |
subfolder_2 |
T_1.sas7bdat |
T_2.sas7bdat |
T_3.sas7bdat |
T_4.sas7bdat |
and then in the second data step, only the tables are deleted.
However, I would like to delete the entirety of the folder. Can someone help?
You could use the %dirtree macro that I found here: https://github.com/sasutils/macros/blob/master/dirtree.sas
%macro dirtree
/*---------------------------------------------------------------------------
Build dataset of files in directory tree(s)
----------------------------------------------------------------------------*/
(directory /* Pipe delimited directory list (default=.) */
,out=dirtree /* Output dataset name */
,maxdepth=120 /* Maximum tree depth */
);
/*---------------------------------------------------------------------------
Use SAS functions to gather list of files and directories
directory - Pipe delimited list of top level directories
out - Dataset to create
maxdepth - Maximum depth of subdirectories to query
Output dataset structure
--NAME-- Len Format Description
FILENAME $256 Name of file in directory
TYPE $1 File or Directory? (F/D)
SIZE 8 COMMA20. Filesize in bytes
DATE 4 YYMMDD10. Date file last modified
TIME 4 TOD8. Time of day file last modified
DEPTH 3 Tree depth
PATH $256 Directory name
Size is not available for the directories.
LASTMOD timestamp is only available on Unix for directories.
Will not scan the subtree of a directory with a path that is
longer then 256 bytes. For such nodes TYPE will be set to L .
----------------------------------------------------------------------------*/
%local fileref ;
%let fileref=__FL__ ;
%if 0=%length(&directory) %then %let directory=. ;
* Setup dataset and seed with starting directory list ;
data &out;
length filename $256 type $1 size 8 date time 4 depth 3 path $256 ;
retain filename ' ' depth 0 type ' ' date . time . size . ;
format size comma20. date yymmdd10. time tod8. ;
do _n_=1 to countw(symget('directory'),'|');
path=scan(symget('directory'),_n_,'|');
output;
end;
run;
%* Allow use of empty OUT= dataset parameter ;
%let out=&syslast;
data &out;
modify &out;
retain sep "%sysfunc(ifc(&sysscp=WIN,\,/))";
retain maxdepth &maxdepth;
* Create FILEREF pointing to current file/directory ;
rc1=filename("&fileref",catx('/',path,filename));
if rc1 then do;
length message $256;
message=sysmsg();
put 'ERROR: Unable to create fileref for ' path= filename= ;
put 'ERROR- ' message ;
stop;
end;
* Try to open as a directory to determine type ;
did=dopen("&fileref");
type = ifc(did,'D','F');
if type='D' then do;
* Make sure directory name is not too long to store. ;
if length(catx('/',path,filename)) > vlength(path) then do;
put 'NOTE: Directory name too long. ' path= filename= ;
type='L';
rc3=dclose(did);
end;
else do;
* Move filename into the PATH and if on Unix set lastmod ;
path=catx(sep,path,filename);
filename=' ';
if sep='/' then do;
lastmod = input(dinfo(did,doptname(did,5)),nldatm100.);
date=datepart(lastmod);
time=timepart(lastmod);
end;
end;
end;
else do;
* For a file try to open file and get file information ;
fid=fopen("&fileref",'i',0,'b');
if fid then do;
lastmod = input(finfo(fid,foptname(fid, 5)), nldatm100.);
date=datepart(lastmod);
time=timepart(lastmod);
size = input(finfo(fid,foptname(fid,ifn(sep='/',6,4))),32.);
rc2 = fclose(fid);
end;
end;
* Update the observation in the dataset ;
replace;
if type='D' then do;
* When current file is a directory add directory members to dataset ;
depth=depth+1;
if depth > maxdepth then put 'NOTE: ' maxdepth= 'reached, not reading members of ' path= ;
else do i=1 to dnum(did);
filename=dread(did,i);
output;
end;
rc3=dclose(did);
end;
* Clear the fileref ;
rc4=filename("&fileref");
run;
%mend dirtree;
Then use the macro to create a directory listing and delete all listed files and folders.
%let topFolderToDelete=c:\temp\deldirtest;
/* create table work.dirtree with directory listing */
%dirtree(&topFolderToDelete);
proc sort data=work.dirtree;
by DESCENDING path DESCENDING type;
run;
/** delete files and folders **/
/* 1. folder separator \ or / (Win or Unix/Linux)? */
data _null_;
set work.dirtree;
if find(path,'\') then sep='\';
else sep='/';
if not missing(sep) then
do;
call symputx('sep',sep);
stop;
end;
run;
/* 2. delete files and folders */
data _null_;
set work.dirtree;
by DESCENDING path DESCENDING type;
fname='tempfile';
if type='F' then
rc=filename(fname, catx("&sep",path,filename));
else
rc=filename(fname, path);
if rc = 0 and fexist(fname) then
rc=fdelete(fname);
rc=filename(fname);
run;
You could use the %dirtree macro that I found here: https://github.com/sasutils/macros/blob/master/dirtree.sas
%macro dirtree
/*---------------------------------------------------------------------------
Build dataset of files in directory tree(s)
----------------------------------------------------------------------------*/
(directory /* Pipe delimited directory list (default=.) */
,out=dirtree /* Output dataset name */
,maxdepth=120 /* Maximum tree depth */
);
/*---------------------------------------------------------------------------
Use SAS functions to gather list of files and directories
directory - Pipe delimited list of top level directories
out - Dataset to create
maxdepth - Maximum depth of subdirectories to query
Output dataset structure
--NAME-- Len Format Description
FILENAME $256 Name of file in directory
TYPE $1 File or Directory? (F/D)
SIZE 8 COMMA20. Filesize in bytes
DATE 4 YYMMDD10. Date file last modified
TIME 4 TOD8. Time of day file last modified
DEPTH 3 Tree depth
PATH $256 Directory name
Size is not available for the directories.
LASTMOD timestamp is only available on Unix for directories.
Will not scan the subtree of a directory with a path that is
longer then 256 bytes. For such nodes TYPE will be set to L .
----------------------------------------------------------------------------*/
%local fileref ;
%let fileref=__FL__ ;
%if 0=%length(&directory) %then %let directory=. ;
* Setup dataset and seed with starting directory list ;
data &out;
length filename $256 type $1 size 8 date time 4 depth 3 path $256 ;
retain filename ' ' depth 0 type ' ' date . time . size . ;
format size comma20. date yymmdd10. time tod8. ;
do _n_=1 to countw(symget('directory'),'|');
path=scan(symget('directory'),_n_,'|');
output;
end;
run;
%* Allow use of empty OUT= dataset parameter ;
%let out=&syslast;
data &out;
modify &out;
retain sep "%sysfunc(ifc(&sysscp=WIN,\,/))";
retain maxdepth &maxdepth;
* Create FILEREF pointing to current file/directory ;
rc1=filename("&fileref",catx('/',path,filename));
if rc1 then do;
length message $256;
message=sysmsg();
put 'ERROR: Unable to create fileref for ' path= filename= ;
put 'ERROR- ' message ;
stop;
end;
* Try to open as a directory to determine type ;
did=dopen("&fileref");
type = ifc(did,'D','F');
if type='D' then do;
* Make sure directory name is not too long to store. ;
if length(catx('/',path,filename)) > vlength(path) then do;
put 'NOTE: Directory name too long. ' path= filename= ;
type='L';
rc3=dclose(did);
end;
else do;
* Move filename into the PATH and if on Unix set lastmod ;
path=catx(sep,path,filename);
filename=' ';
if sep='/' then do;
lastmod = input(dinfo(did,doptname(did,5)),nldatm100.);
date=datepart(lastmod);
time=timepart(lastmod);
end;
end;
end;
else do;
* For a file try to open file and get file information ;
fid=fopen("&fileref",'i',0,'b');
if fid then do;
lastmod = input(finfo(fid,foptname(fid, 5)), nldatm100.);
date=datepart(lastmod);
time=timepart(lastmod);
size = input(finfo(fid,foptname(fid,ifn(sep='/',6,4))),32.);
rc2 = fclose(fid);
end;
end;
* Update the observation in the dataset ;
replace;
if type='D' then do;
* When current file is a directory add directory members to dataset ;
depth=depth+1;
if depth > maxdepth then put 'NOTE: ' maxdepth= 'reached, not reading members of ' path= ;
else do i=1 to dnum(did);
filename=dread(did,i);
output;
end;
rc3=dclose(did);
end;
* Clear the fileref ;
rc4=filename("&fileref");
run;
%mend dirtree;
Then use the macro to create a directory listing and delete all listed files and folders.
%let topFolderToDelete=c:\temp\deldirtest;
/* create table work.dirtree with directory listing */
%dirtree(&topFolderToDelete);
proc sort data=work.dirtree;
by DESCENDING path DESCENDING type;
run;
/** delete files and folders **/
/* 1. folder separator \ or / (Win or Unix/Linux)? */
data _null_;
set work.dirtree;
if find(path,'\') then sep='\';
else sep='/';
if not missing(sep) then
do;
call symputx('sep',sep);
stop;
end;
run;
/* 2. delete files and folders */
data _null_;
set work.dirtree;
by DESCENDING path DESCENDING type;
fname='tempfile';
if type='F' then
rc=filename(fname, catx("&sep",path,filename));
else
rc=filename(fname, path);
if rc = 0 and fexist(fname) then
rc=fdelete(fname);
rc=filename(fname);
run;
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!
What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.