BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Babado
Fluorite | Level 6

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?

1 ACCEPTED SOLUTION

Accepted Solutions
Patrick
Opal | Level 21

You could use the %dirtree macro that I found here: https://github.com/sasutils/macros/blob/master/dirtree.sas 

Spoiler
%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;

 

View solution in original post

2 REPLIES 2
Patrick
Opal | Level 21

You could use the %dirtree macro that I found here: https://github.com/sasutils/macros/blob/master/dirtree.sas 

Spoiler
%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;

 

Babado
Fluorite | Level 6
Works like charm. Thanks.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
SAS Enterprise Guide vs. SAS Studio

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 2 replies
  • 447 views
  • 4 likes
  • 2 in conversation