Looking at some SAS code that was working very hard to figure out what directory to use for default output I was reminded of a macro that Tom Hoffman created for me almost 20 years ago that I still use all of the time. So I have posted a version of it on github
The idea is simple. Create a fileref pointing to the current working directory and then ask SAS what path that fileref points to. The path is then returned as the content of the macro. That way you can embed the macro call into other SAS statements.
%macro curdir;
/*----------------------------------------------------------------------
Returns the current SAS directory physical name.
----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
Originally developed by Tom Hoffman.
Posted in memory of Tom and Fan.
-----------------------------------------------------------------------
Usage:
%put %curdir is the current directory.;
------------------------------------------------------------------------
Notes:
-----------------------------------------------------------------------
History:
11MAR99 TRHoffman Creation - with help from Tom Abernathy.
06DEC00 TRHoffman Used . notation to refernece current directory as
suggested by Fan Zhou.
----------------------------------------------------------------------*/
%local fr rc curdir;
%let rc = %sysfunc(filename(fr,.));
%let curdir = %sysfunc(pathname(&fr));
%let rc = %sysfunc(filename(fr));
&curdir
%mend curdir;
Big one @Tom 🙂 Thanks to you and your peers
The following code is the same with your macro ?
%let path=%sysfunc(pathname(SASROOT));
%put &path;
The libref SASROOT points to where SAS is installed, not the current working directory for the process that is running SAS.
If you run SAS from the command line the current directory is normally the directory where you issued the command. If you are using a server (via SAS/Studio or EG for example) then it is normally the directory where the application server was launched.
But if your SAS code had submitted any cd commands then the current directory could be very different that what is was when the SAS program started.
sasroot is the name of an environment variable:
%put sasroot: %sysget(sasroot);
This is the path your work folder:
%put sasuser: %sysfunc(getoption(sasuser));
if you are submitting programs in batch then startup-only option sysin contains the path/filename.ext
%put sysin: %sysfunc(getoption(sysin));
I can't remember the session option/macro-variable which has this path+filename.
trivial comment: you can code this without the assignment and reference to curdir
%let rc = %sysfunc(filename(fr,.));
/* %let curdir = */ %sysfunc(pathname(&fr));
%let rc = %sysfunc(filename(fr));
/*&curdir */
%mend curdir;
Two comments:
1, it looks only work in SAS DM, in EG it returns an incorrect path "C:\WINDONS\system32" ;
2, please add a semi-colon in the end of &curdir in your code just like "%put &curdir;"
Two comments:
1, it looks only work in SAS DM, in EG it returns an incorrect path "C:\WINDONS\system32" ;
That seems like a likely current directory for the process that is running SAS. If you want to change it you would need to submit an operating system command at some point in your SAS code. Such as :
x "cd c:\My Shared Data Folder\";
2, please add a semi-colon in the end of &curdir in your code just like "%put &curdir;"
Not sure what you are talking about here. The example line in the program header does include a semi-colon to end the %PUT statement.
%put %curdir is the current directory.;
What would this be useful for?
When you make a "function" style macro the only SAS code it should generate are the characters of the data value that you wan it to generate. If you include a semi-colon in the SAS code that the macro generates then you can no longer use the macro call as if it was a function. That extra semi-colon would cause havoc with the actual SAS statement that you are trying to use the macro function to generate.
If I tried to use the macro call in a single statement like:
%let target=%curdir/logs;
And the current directory was /home/mydir then SAS would see the result as these TWO statements.
%let target=/home/mydir;
/logs;
And SAS would not understand what a command like
/logs;
was supposed to mean.
What would this be useful for?
The same reason that you would call for the current directory in any other programming language.
The best use I have put it to is to have SAS automatically detect what project I am working on based on which directory I was in when I launched SAS. So if my file system is organized to have tasks nested under projects I could parse the current directory to figure out which task for which project is being worked on.
%let curdir=%curdir;
%let projcode=%scan(&curdir,4,/);
%let taskcode=%scan(&curdir,5,/);
proc sql noprint;
select title,manager
into :proj_title trimmed
, :manager_name trimmed
from sysdata.projects
where project="&projcode" and task="&taskcode"
;
quit;
TITLE1 "&proj_title";
FOOTNOTE1 "See &manager_name";
...
So why not just use _CLIENTPROJECTPATH? I use it to create subdirectories underneath it for staging data, validation, logs and output.
3 %LET _CLIENTTASKLABEL='Autoexec';
4 %LET _CLIENTPROCESSFLOWNAME='321_BH_EDPresentations';
5 %LET _CLIENTPROJECTPATH='S:\_Louisiana\321_BH_EDPresentations\321_BH_EDPresentations parallel 20180815 1000.egp';
6 %LET _CLIENTPROJECTPATHHOST='PHLWL131J2J';
7 %LET _CLIENTPROJECTNAME='321_BH_EDPresentations parallel 20180815 1000.egp';
Hi @tomrvincent - _CLIENTPROJECTPATH is available only in SAS Enterprise Guide. And, as the name implies, it's the path of the Windows client folder where the EG project lives -- might not be the same as the SAS server location where your session is operating.
@ChrisHemedinger I use it as a base, then convert the drive to what SAS understands (in my case, //mnt/nfs/prod/Teams/). I haven't used base SAS in 30 years, so I forget it's out there. 🙂
I want current program name in macro variable. How do i get that.
For ex: if my program name is DM.sas then in DM.sas program i wanted to create macro varibale named PGM and want to load value DM into PGM macro variable.
This is a great tip, @Tom. I've highlighted this and the new DLGCDIR function (which allows you to change the current directory) in this blog post: Manage the current directory within your SAS program.
@vandhan, Look into
http://www2.sas.com/proceedings/forum2008/023-2008.pdf
for how to use environment variable SAS_EXECFILENAME.
Note the SAS_EXECFILENAME is an environment variable that is set by the "enhanced" editor in PC SAS. It is not set by the normal program editor, on either Windows or Unix operating system. And, of course, It will not be set if you submit your program from the command line.
Also if you haven't yet saved the program you are editing to a file then it will not be set. Or the program it points to might look nothing like the actual code you have submitted.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.