Manage the current directory within your SAS program

4

The concept of "current working directory" is important within any SAS program that reads or creates external files. In SAS, when you reference a file location with a relative path (for example, "./projects/mydata.pdf"), that file reference resolves to an absolute path by way of the working directory. You can control the initial working directory by modifying the shell scripts that launch the SAS process, or by specifying the SASINITIALFOLDER option in the SAS command or config file. But if you're using SAS Enterprise Guide or SAS Studio, it's likely that you don't have the ability to control how the SAS process starts. But don't worry -- there is still a way to find and change the working directory within your SAS programs.

Find the current directory in SAS

Tom (one of our SAS Communities Super Users) shared a simple SAS macro that allows you to learn the current working directory. The macro uses a trick to assign a SAS fileref to the current path ('.'), grab the full path of that fileref by using the PATHNAME function, and then clear the fileref.

Read the article for the full source (it's only about 7 lines). Here's how you would use it:

56         %put Current path is %curdir;
Current path is C:\WINDOWS\system32

As you might infer from my example here, I'm running this on a managed Windows environment. Most users cannot write to the "C:\WINDOWS\system32" path (and would not want to), so any relative file paths in my SAS code would cause errors. Maybe you've seen something like this:

25         ods html file="./test.html";
NOTE: Writing HTML Body file: ./test.html
ERROR: Insufficient authorization to access C:\WINDOWS\system32\test.html.
ERROR: No body file. HTML output will not be created.

If I want to use a relative path, I need to change the current working directory. Fortunately, there's a simple way to do that.

Change the current directory in SAS

Use the DLGCDIR function to change the working directory for your current SAS session. The DLGCDIR function was added in SAS 9.4 Maintenance 4 (released in 2016). Now I can change the working directory early in my program, and all relative file paths will resolve accordingly.

/* working path for my projects */
%let rc = %sysfunc(dlgcdir('u:/projects'));
 
ods html file="./test.html";
proc print data=sashelp.class; run;
ods html close;

I can use my account-specific environment variables to make these paths work for all users. For example, on Windows I can reference the USERPROFILE environment variable. (On Unix, I can use the HOME environment variable instead.)

/* working path for my projects */
%let user = %sysget(USERPROFILE);
%let rc = %sysfunc(dlgcdir("&user./Documents"));
 
/* create an output data folder if needed */
options dlcreatedir;
libname outdata "./data";
 
ods html file="./test.html";
data outdata.class;
 set sashelp.class;
run;
proc print data=outdata.class; run;
ods html close;

Here's my log output. Notice how the HTML file and the output data folder are both created at locations relative to my home directory.

25         /* working path for my projects */
26         %let user = %sysget(USERPROFILE);
27         %let rc = %sysfunc(dlgcdir("&user./Documents"));
NOTE: The current working directory is now "C:\Users\sascrh\Documents".
28         
29         options dlcreatedir;
30         libname outdata "./data";
NOTE: Library OUTDATA was created.
NOTE: Libref OUTDATA was successfully assigned as follows: 
      Engine:        V9 
      Physical Name: C:\Users\sascrh\Documents\data
31         
32         ods html file="./test.html";
NOTE: Writing HTML Body file: ./test.html
33         data outdata.class;
34          set sashelp.class;
35         run;

If using SAS Enterprise Guide, you can add DLGCDIR function steps to the startup statements that run when you connect to SAS, ensuring that your working directory starts in a valid location for SAS output. You can specify those statements in Tools->Options->SAS Programs, "Submit SAS code when server is connected." A SAS administrator can also add code to the AUTOEXEC file that runs when the SAS session begins, thus helping to manage this for larger groups of SAS users.

See also

Share

About Author

Chris Hemedinger

Senior Manager, SAS Online Communities

+Chris Hemedinger is the manager of SAS Online Communities. Since 1993, Chris has worked for SAS as an author, a software developer, an R&D manager and a consultant. Inexplicably, Chris is still coasting on the limited fame he earned as an author of SAS For Dummies.  He also hosts the SAS Tech Talk webcasts each year from SAS Global Forum, connecting viewers with smart people from SAS R&D and the impressive work that they do.

Related Posts

4 Comments

    • Chris Hemedinger
      Chris Hemedinger on

      Good question! I think the answer is Yes, as long as the "change directory" operation is run in each of the nodes when you start. That means as part of an AUTOEXEC or the standard snippet of code that runs when you connect to a server. It's worth testing to make sure it does what you need. Also, as you know, since each grid node has its own file system, you would target a shared network file location for any output (data sets, other files) that you want to persist after the work is done.

  1. When you ran this, was test.html created within C:\Users\sascrh\Documents? When I ran it, test.html went into my SAS temporary working directory, as it normally does -- C:\Users\myname\AppData\Local\Temp\SAS Temporary Files\_TD5792_L56LT5CG426HQKP_

    • Chris Hemedinger
      Chris Hemedinger on

      Yes, the directory changes and output is directed to my documents folder. Check your USERPROFILE value.

      %let user = %sysget(USERPROFILE);
      %put &=user;
      

      And make sure you use the dot-slash notation in your ODS path:

      ods html file="./test.html";
      

      And if you're using EG and already have HTML destination turned on, remember that you'll get TWO HTML outputs -- one is the EG default, and one is the named file in your ODS statement. You'll have to turn off the HTML destination in your EG options or use ODS CLOSE _ALL_ if you want just the one output.

Leave A Reply

Back to Top