BookmarkSubscribeRSS Feed
Tushar
Obsidian | Level 7

Hi All,

 

from below code I want to create dataset which will have this two column path and lname which gate value from this two macro variable &dir and &name respective. can you please help me to put my output statement in right position so that I can create data set ?

 


%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(c:\temp,sas)
3 REPLIES 3
ChrisNZ
Tourmaline | Level 20

Sadly SAS still doesn't have write functions to data sets.

So you need something like this:

%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;                                                                                                                                 
                          
data OUT; 
length DIR NAME $200;
                                                                                                              
   /* 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;      

DIR="&dir"; NAME="&name"; output;
                                                                                                          
      %end;                                                                                                                             
     /* If directory name call macro again */                                                                                           
      %else %if %qscan(&name,2,.) = %then %do;                                                                                          
        %drive(&dir\%unquote(&name),&ext)                                                                                               
      %end;                                                                                                                             
                                                                                                                                        
   %end;                  

run;                                                                                                              
                                                                                                                                        
  /* Closes the directory and clear the fileref */                                                                                      
  %let rc=%sysfunc(dclose(&did));                                                                                                       
  %let rc=%sysfunc(filename(filrf));                                                                                                    
                                                                                                                                        
%mend drive;       

 

ScottBass
Rhodochrosite | Level 12

This doesn't do exactly what you want, as it does not support full recursion.  Perhaps someone smarter than me (@ChrisNZ?) can get recursion working.

 

However, this does one-level recursion:

 

proc delete data=filelist;
run;
%dirlist(dir=C:\Temp,type=d,data=dirlist)
%macro code;
   %let fullname=%trim(&fullname);
   %dirlist(dir=&fullname,data=temp,filter=ext='sas');
   proc append base=filelist data=temp;
   run;
%mend;
%loop_control(control=dirlist);

See:

https://github.com/scottbass/SAS/blob/master/Macro/dirlist.sas

https://github.com/scottbass/SAS/blob/master/Macro/loop.sas

https://github.com/scottbass/SAS/blob/master/Macro/loop_control.sas

https://github.com/scottbass/SAS/blob/master/Macro/parmv.sas

 

Also, I think you'd get much better performance if you did most of this code in the data step rather than macro.

 

Something like:

 

%macro drive(dir,ext);  
   data dirlist;
      rc=filename("dirlist","&dir");
      did=dopen("dirlist");
      do i=1 to dnum(did);
         name=dread(did,i);
         if scan(name,-1,'.')="&ext" then output;
      end;
      rc=dclose(did);
      rc=filename("dirlist");

      * perhaps implement recursion with link/return statements? ;
   run;
%mend; 
%drive(C:\Temp,sas);

The only macro "bits" are the parameters for file path and desired extension - everything else is a data step.  If you're looping via macro, that will likely be orders of magnitude slower than the data step.

 

@ChrisNZ if you do get recursion working, and it can be added to my dirlist macro, that would be great!  I just haven't bothered with that for now.

 


Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.
ScottBass
Rhodochrosite | Level 12

Also, do you have ALLOWXCMD available in your environment?

 

What happens if you run this code (adjust if you're running Linux):

 

filename dirlist pipe "dir /b /s \\sascs\linkage\RL_content_snapshots";
data dirlist1;
   infile dirlist lrecl=256 truncover;
   input;
   filename=_infile_;
run;

* or ;

filename dirlist pipe "powershell ""Get-ChildItem -recurse \\sascs\linkage\RL_content_snapshots | ForEach-Object {$_.Fullname}"" ";
data dirlist2;
   infile dirlist lrecl=256 truncover;
   input;
   filename=_infile_;
run;

Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.

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!
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
  • 543 views
  • 0 likes
  • 3 in conversation