Regardless of the environment in which you run SAS (whether it is SAS® Foundation, SAS® Studio, or SAS® Enterprise Guide®), SAS uses a default location on your host system as a working directory. When you do not specify the use of a different directory within your code, the default location is where SAS stores output.
Beginning with SAS® 9.4 TS1M4, you can use a new DATA step function, DLGCDIR, to change the location for your working directory. You can use this function in Microsoft Windows or UNIX/Linux environments.
Make sure that any directory that you specify with the DLGCDIR function is an existing directory that you have Write or Update access to.
Finding Out What Your Current Directory Is
To determine what your current working directory in SAS is, submit the following code:
data _null_; rc=dlgcdir(); put rc=; run;
Changing Your Windows Directory
The following sample code for Windows sets the working directory in SAS as the TEMP folder on your C: drive:
data _null_; rc=dlgcdir("c:\temp"); put rc=; run;
Changing Your Linux Directory
This sample code (for a Linux environment) changes the working directory in SAS to /u/your/linux/directory:
data _null_; rc=dlgcdir("/u/your/linux/directory"); put rc=; run;
Changing Your Directory: Other Tips
The DLGCDIR function temporarily changes the working directory for the current SAS or client session. However, you can create an autoexec file that contains the DATA step code that uses the DLGCDIR function. The autoexec file then executes the code each time you invoke SAS.
In most situations, it is still recommended that you specify the intended target directory for the Output Delivery System (ODS) and in other SAS statements. For example, when you use the ODS HTML statement, you should specify the target directory with the PATH option, as shown here:
ods html path="c:\temp" (url=none) file="sasoutput.html";
Similarly, with the ODS PDF statement, you should specify the target directory with the FILE option, as shown here:
ods pdf file="c:\temp\sasoutput.pdf";
I hope you've found this post helpful.
Just noticed this addition. It is a little quirky in that it does not return the current directory as the output of the function. Instead it writes a NOTE (or WARNING or ERROR) to the SAS log. The value returned is just a numeric status code with 0 meaning success. Also it does NOT have the problems some have mentioned in the comments. It will not change the current directory to a path that does not exist, in that case the current directory is left unchanged.
I have updated my 24 year old macro for that does return the current directory to also now allow you to change the current directory by adding an optional input argument. You can get the %CURDIR() macro from GITHUB, https://github.com/sasutils/macros/blob/master/curdir.sas
Excellent. Thank you, Martin.
I notice that the change of directory does not apply to an "ls -l" (UNIX directory listing) piped into an INFILE. Has there been any thought as to extending the functionality to a directory listing or other PIPE input to an INFILE?
For example, the DLGCDIR function does not apply to the below (but it would be nice if it did). 🙂
** Pipe a single column directory listing ("ls -1") to an INFILE. **;
INFILE "ls -1 *&suffix" PIPE
LENGTH = _Filename_Length
END = _End_of_Listing
OBS = &List_Obs
Hi Jim, You are correct in that the DLGCDIR function does not have any affect when using "ls -l" to pipe a directory listing into an INFILE. At first glance, I would have thought that it would apply, but when I test it here, it actually does not apply in this case. To change the default directory used by INFILE "ls -l", I first need to change the default directory via the X command, for example:
X "cd /tmp";
But in order to use the X command in SAS, you will have to make sure that your invocation of SAS is configured to allow the X command. But as far as the original question is concerned, let me research it a bit more from my side. Regards, Martin
Please let me know if you come up with something in your research.
In the mean time, what I've done is to simply combine commands in my FILENAME separated by a comma. For example:
** FileName In_List pipes in a directory listing. **;
FILENAME In_List PIPE "cd &XML_Path;ls -1a %Set_Grep";
The first portion of the command (before the semi-colon) changes the directory, and the second part (after the semi-colon), runs a directory listing, the output of which is piped back to SAS. %Set_Grep is just a little macro function that will grep out only those files I'm looking for based on some text string, in this case "txt".
Hi Jim, I have officially added your issue to the list of issues for SAS R&D to address in a future release of SAS. Since the issue you are running into might be outside the control of the DLGCDIR function, I cannot guarantee that we will be able to address it in a future release. But at least this is now something that SAS development will investigate. Regards, Martin
I found that and X statement (e.g. X "cd /tmp") doesn't have the desired result because future X statements launch a new shell and revert back to the original working directory. Jim's example works by sending two commands each time, effectively this means you'd have to change the working directory every time the pipe or X statement or pipe is executed. For those looking for a command that affects everything - future pipes, X statement, and the SAS session, I ended up using a call system statement. It seems this actually affects the current session instead of only a shell sub-process. E.g.:
call system('cd /tmp');
That DLG prefix was previously a hint that the function operated to open a dialog box in interactive SAS - hence the lack of returned value.
Sometimes I assume too much
Does the dlgcdir() function work within %SYSFUNC()?
Very useful. It would be even more useful if your first example:
stored the value into a data step variable rather than writing it to the log as a NOTE:. I could see using some logic to make decision based on the working directory folder. Still, quite useful.
Hi Al, After researching this a bit more here, it turns out that the DLGCDIR function is not designed to return the current working directory in a DATA step variable or macro variable. But the following sample code when run on Windows creates both a DATA step variable and a macro variable that contains the current working directory:
filename curdir pipe 'echo %CD%';
infile curdir truncover;
length currentdir $ 100;
input currentdir $char100.;
%put Current working directory is &curwdir;
Great to see that SAS 9.4 M4 has made it possible to discover and change the current working directory. The need for this has been obvious for so long that the bodged workaround with X was documented. Unix has been able to do this from the beginning (pre-1986) and MS-DOS from very early. What took so long? And what is the DLG part of the name? I would have found something like CHGWDIR easier to remember, if you must limit to 7 characters. This kind of obscurity will not convert new users to SAS.
No running of system commands through PIPE or X was required
Filename here '.' ;
%let here= %sysfunc( pathname( here ));
should have provided what you wanted since EG became available
Martin, thank you for this blog post. It's a very useful new SAS function that allows dynamically (programmatically) change your working directory. Could you please let us know what command in the SAS configuration file (sasv9.cfg) or elsewhere controls its default location? I would also emphasize that "working" directory is NOT a location of the WORK library.
Hi Leonid, With an install of SAS on Windows, you can use the SASINITIALFOLDER setting in your SAS configuration file (SASV9.CFG file) to set the default "working" directory at SAS invocation. For example, you can set this in your SASV9.CFG file on Windows by adding a line to the top of the config file that looks like this:
SASINITIALFOLDER and dlgcdir() set 2 different default directories for some reason. Unsure how these default locations differ.
The DLGCDIR() function should return the same directory name as is set by the SASINITIALFOLDER option in your SAS configuration file. If the DLGCDIR() function returns something different, I am wondering if perhaps something previously in your code changed the default current working directory to a value other than that set by the SASINITIALFOLDER option. But if you would like to, please open a Tech Support track with us on this so I can work directly with you.