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

I have a UNIX server that contain the following folder structure:

Root: /sas/config/master.data/

 

 

 

1st Layer (Possible folders):

/sas/config/master.data/12312016
/sas/config/master.data/06302017
/sas/config/master.data/08312017
/sas/config/master.data/johncena
/sas/config/master.data/brock123
/sas/config/master.data/elonmusk

 

2nd Layer 

/sas/config/master.data/johncena/09302019
/sas/config/master.data/johncena/04302012
/sas/config/master.data/brock123/02282013
/sas/config/master.data/elonmusk/01312020
/sas/config/master.data/elonmusk/03312021

Do notice that only those english name subfolders (eg. johncena) are being pointed out here assuming that it contains a MMDDYYYY folder inside. I can achieve this by checking it with anydate function (eg. folderdate=input(fname,anydtdte.);). Also, the folder master.data contains a dot (may cause issue if i understand correctly).

 

 

 

By looking at the folder structure above, we can tell that only the root directory is fixed. After the root directory, there are 2 more levels that are dynamic which require further looping.

 

Ultimately, I will need to store this into a SAS Dataset so that I can assign it into macro for generating mv -f command to either remove it or move or copy to another directory within the UNIX server.

 

Now my trouble is, I have a script that I referred to SAS documentation but I couldn't find the right way and logic to scan unix directory dynamically with a check for 2 additional layers (refer to 2nd Layer explanation.) despite me knowing that there is a function to check if the folder contains a valid date format or not. 

 

The UNIX directory scan script as below. I can execute it but it will only show in log, not storing into a table with the full directory for me to further process. Would this be the most efficient script for what I am aimed to do?

%macro drive(dir,ext);                                                                                                                  
  %local filrf rc did memcnt name i;                                                                                                    
                                                                                                                                        
  /* Assigns a fileref to the directory and opens the directory */                                                           
  %let rc=%sysfunc(filename(filrf,&dir));                                                                                               
  %let did=%sysfunc(dopen(&filrf));                                                                                                     
                                                                                                                                        
  /* Make sure directory can be open */                                                                                                 
  %if &did eq 0 %then %do;                                                                                                              
   %put Directory &dir cannot be open or does not exist;                                                                                
   %return;                                                                                                                             
  %end;                                                                                                                                 
                                                                                                                                        
   /* Loops through entire directory */                                                                                                 
   %do i = 1 %to %sysfunc(dnum(&did));                                                                                                  
                                                                                                                                        
     /* Retrieve name of each file */                                                                                                   
     %let name=%qsysfunc(dread(&did,&i));                                                                                               
                                                                                                                                        
     /* Checks to see if the extension matches the parameter value */                                                                   
     /* If condition is true print the full name to the log        */                                                                   
      %if %qupcase(%qscan(&name,-1,.)) = %upcase(&ext) %then %do;                                                                       
        %put &dir/&name;                                                                                                                
      %end;                                                                                                                             
     /* If directory name call macro again */                                                                                           
      %else %if %qscan(&name,2,.) = %then %do;                                                                                          
        %drive(&dir/%unquote(&name),&ext)                                                                                               
      %end;                                                                                                                             
                                                                                                                                        
   %end;                                                                                                                                
                                                                                                                                        
  /* Closes the directory and clear the fileref */                                                                                      
  %let rc=%sysfunc(dclose(&did));                                                                                                       
  %let rc=%sysfunc(filename(filrf));                                                                                                    
                                                                                                                                        
%mend drive;                                                                                                                            
                                                                                                                                        
/* First parameter is the directory of where your files are stored. */                                                                  
/* Second parameter is the extension you are looking for.           */                                                                  
%drive(/sas/config/master.data/,sas)     
1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

You can use the MODIFY statement functionality of a DATA step to scan through a directory tree without have to actually write a recursive function.

 

Use this macro.

https://github.com/sasutils/macros/blob/master/dirtree.sas

 

If you only want to go down two levels use the MAXDEPTH option.

%dirtree
/*---------------------------------------------------------------------------
Build dataset of files in directory tree(s)
----------------------------------------------------------------------------*/
(/sas/config/master.data    /* Pipe delimited directory list (default=.) */
,out=dirtree  /* Output dataset name */
,maxdepth=2 /* Maximum tree depth */
);

To get list of directories that are two levels below your starting path you could use:

data level2;
  set dirtree;
  where level=2 and type='D';
run;

 

View solution in original post

3 REPLIES 3
ChrisNZ
Tourmaline | Level 20
  /* If directory name call macro again */          

The way to test this is to use the dopen() function

Tom
Super User Tom
Super User

You can use the MODIFY statement functionality of a DATA step to scan through a directory tree without have to actually write a recursive function.

 

Use this macro.

https://github.com/sasutils/macros/blob/master/dirtree.sas

 

If you only want to go down two levels use the MAXDEPTH option.

%dirtree
/*---------------------------------------------------------------------------
Build dataset of files in directory tree(s)
----------------------------------------------------------------------------*/
(/sas/config/master.data    /* Pipe delimited directory list (default=.) */
,out=dirtree  /* Output dataset name */
,maxdepth=2 /* Maximum tree depth */
);

To get list of directories that are two levels below your starting path you could use:

data level2;
  set dirtree;
  where level=2 and type='D';
run;

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

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.

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
  • 3 replies
  • 530 views
  • 4 likes
  • 4 in conversation