I have a number of directories each containing the same sas program. I would like to
set some macro variables in a small sas file in each of these directories and then
include it in the main sas program. Because the main sas program can be copied
to a number of directories I don't want to use an absolute path in the include statement.
Is there a way to use relative paths? For example, if I had this include statement in
my main sas program:
%include 'linemg.sas';
and then tried to run the main sas program from within the sas application window, I get
an error stating that it cannot open the file. If I specify the absolute path in the include
statement it works but I don't want to have to do that. Does the concept of a current working
directory exist in sas?
If the relative path you need is relative to the location of the currently executing SAS program I think you are looking for the automatic SAS variables SAS_EXECFILEPATH and SAS_EXECFILENAME.
This requires the executing code to have been saved. The macro variable PATH should be
%let a=%sysget(SAS_EXECFILEPATH);
%let b=%sysget(SAS_EXECFILENAME);
%let path= %sysfunc(tranwrd(&a,&b,''));
%put &path;
The macro variable PATH should be ready to use as %include "&path.codefile.sas";
There is a 'current folder'. Set or change it with SAS statement:
X CD "your preferred folder";
The default is set by the current folder in which SAS is launched.
Relative folders can be defined in the normal way
Here is ./
Parent ../
Child folder ./childfolder
Cousin folder ../cousin
Use \ if not on unix (only sometimes do we get away with / on windows)
Peter
Take a look at the various options expressed throughout the following sas-l thread:
http://listserv.uga.edu/cgi-bin/wa?A2=ind1010a&L=sas-l&D=0&O=D&m=22408&P=13821
Hi Art,
This is exactly what I was looking for. However, I can't seem to get it to work. I tried this piece of code:
* ConCheck.sas ;
%include 'c:\SASUtils\dissectionIO20110912.sas';
%include 'c:\SASUtils\Current.sas';
%Current;
%include "&Current\linemg.sas"';
The output log shows this:
1 * ConCheck.sas ;
2 %include 'c:\SASUtils\dissectionIO20110912.sas';
22 %include 'c:\SASUtils\Current.sas';
38 %Current;
NOTE: The infile PRESENT is:
Unnamed Pipe Access Device,
PROCESS=CD,RECFM=V,LRECL=256
Stderr output:
The handle is invalid.
NOTE: 0 records were read from the infile PRESENT.
NOTE: DATA statement used (Total process time):
real time 0.14 seconds
cpu time 0.03 seconds
NOTE: Libref CURRENT was successfully assigned as follows:
Engine: V9
Physical Name: C:\Users\barrisw\
39 %include "&Current\linemg.sas";
WARNING: Physical file does not exist, C:\linemg.sas.
ERROR: Cannot open %INCLUDE file \linemg.sas.
Here is a workaround. Assuming all of your directories which contains SAS code are under c:\temp.
filename fname pipe 'dir c:\temp\*.sas /S /b'; data _null_; infile fname; input; call symputx(scan(_infile_,-2,'.\'),_infile_); run; %put _user_; %include "&a1"; 86 %put _user_; GLOBAL A1 c:\temp\a\a1.sas GLOBAL A2 c:\temp\a\a2.sas GLOBAL B1 c:\temp\b\b1.sas GLOBAL B2 c:\temp\b\b2.sas 87 %include "&a1";
Ksharp
消息编辑者为:xia keshan
Hi Ksharp,
Thanks for the advice. However, when I tried to run this I got errors. Perhaps I'm not doing this correctly:
Plus, I dont' want to have to specify the directory in the sas program.
filename fname pipe 'dir m:\L01mg300\*.sas /S /b';
data _null_;
infile fname;
input;
call symputx(scan(_infile_,-2,'.\'),_infile_);
run;
%put _user_;
%include "&a1";
Log output:
NOTE: Copyright (c) 2002-2008 by SAS Institute Inc., Cary, NC, USA.
NOTE: SAS (r) Proprietary Software 9.2 (TS2M3)
NOTE: This session is executing on the X64_DSRV08 platform.
NOTE: SAS initialization used:
real time 1.96 seconds
cpu time 0.79 seconds
1 filename fname pipe 'dir m:\L01mg300\*.sas /S /b';
2 data _null_;
3 infile fname;
4 input;
5 call symputx(scan(_infile_,-2,'.\'),_infile_);
6 run;
NOTE: The infile FNAME is:
Unnamed Pipe Access Device,
PROCESS=dir m:\L01mg300\*.sas /S /b,RECFM=V,
LRECL=256
Stderr output:
There is not enough space on the disk.
NOTE: 0 records were read from the infile FNAME.
NOTE: DATA statement used (Total process time):
real time 0.15 seconds
cpu time 0.03 seconds
7 %put _user_;
8 %include "&a1";
WARNING: Apparent symbolic reference A1 not resolved.
WARNING: Physical file does not exist, C:\Users\barrisw\&a1.
ERROR: Cannot open %INCLUDE file &a1.
Wes, Do you happen to have the name(s) current and/or present reserved for something else? It worked perfectly on my machine.
You shouldn't end the macro call with a semi-colon, but that wouldn't cause the error you received.
Hi Art,
I don't think that Current or Present are defined anywhere else. I've found that if I navigate inside Windows Explorer to the sas file and double-click on it, it opens the SAS environment window. If I then click on the "run" icon it works. However, if I first start the SAS environment and then use File-> Open Program and then navigate to that same sas file, and then run it, it issues the errors I mentioned.
Successful run (double clicking on sas file in windows explorer):
1 * ConCheck.sas ;
2 %include 'c:\SASUtils\dissectionIO20110912.sas';
22 %include 'c:\SASUtils\Current.sas';
38 %Current;
NOTE: The infile PRESENT is:
Unnamed Pipe Access Device,
PROCESS=CD,RECFM=V,LRECL=256
NOTE: 1 record was read from the infile PRESENT.
The minimum record length was 11.
The maximum record length was 11.
NOTE: DATA statement used (Total process time):
real time 0.03 seconds
cpu time 0.00 seconds
NOTE: Libref CURRENT was successfully assigned as follows:
Engine: V9
Physical Name: M:\L01mg300
39 %include "&Current\linemg.sas";
Failed run (navigating to file from sas environment):
1 * ConCheck.sas ;
2 %include 'c:\SASUtils\dissectionIO20110912.sas';
22 %include 'c:\SASUtils\Current.sas';
38 %Current;
NOTE: The infile PRESENT is:
Unnamed Pipe Access Device,
PROCESS=CD,RECFM=V,LRECL=256
Stderr output:
The handle is invalid.
NOTE: 0 records were read from the infile PRESENT.
NOTE: DATA statement used (Total process time):
real time 0.03 seconds
cpu time 0.00 seconds
NOTE: Libref CURRENT was successfully assigned as follows:
Engine: V9
Physical Name: C:\Users\barrisw\
39 %include "&Current\linemg.sas";
WARNING: Physical file does not exist, C:\linemg.sas.
ERROR: Cannot open %INCLUDE file \linemg.sas.
It looks like your CURRENT macro is just creating a LIBREF and is not assigning anything to the CURRENT macro variable.
If it does assign a value to the CURRENT macro variable without first defining it as local then if you define it first the macro will be able to return a value. (Look at the concept of LOCAL and GLOBAL macro variables).
So try:
%let current=;
%current;
%put current="¤t";
To see if that works.
Another idea is just use . as the current directory. This will reference whatever your SAS process considers the current working directory.
Also you can use the PATHNAME function to get the path to the CURRENT library that the macro is creating.
%current;
%let current=%sysfunc(pathname(current));
Thanks Tom.
Attempting your first suggestion:
1774 %let Current=;
1775 %Current;
NOTE: The infile PRESENT is:
Unnamed Pipe Access Device,
PROCESS=CD,RECFM=V,LRECL=256
Stderr output:
The handle is invalid.
NOTE: 0 records were read from the infile PRESENT.
NOTE: DATA statement used (Total process time):
real time 0.03 seconds
cpu time 0.01 seconds
NOTE: Libref CURRENT was successfully assigned as follows:
Engine: V9
Physical Name: C:\Users\barrisw\
1776 %put Current="&Current";
Current=""
1777 %include "&Current\linemg.sas";
WARNING: Physical file does not exist, C:\linemg.sas.
ERROR: Cannot open %INCLUDE file \linemg.sas.
I've already tried usine ./linemg.sas but the current working directory inside the SAS environment is not the same as where the .sas file sits in the filesystem.
using sysfunc and pathname...
looks like it is picking up my home directory and not the directory where the .sas program exists.
NOTE: Libref CURRENT was successfully assigned as follows:
Engine: V9
Physical Name: C:\Users\barrisw
1341 %let Current=%sysfunc(pathname(Current));
1342 %include "&Current\linemg.sas";
WARNING: Physical file does not exist, C:\Users\barrisw\linemg.sas.
ERROR: Cannot open %INCLUDE file C:\Users\barrisw\linemg.sas.
If the relative path you need is relative to the location of the currently executing SAS program I think you are looking for the automatic SAS variables SAS_EXECFILEPATH and SAS_EXECFILENAME.
This requires the executing code to have been saved. The macro variable PATH should be
%let a=%sysget(SAS_EXECFILEPATH);
%let b=%sysget(SAS_EXECFILENAME);
%let path= %sysfunc(tranwrd(&a,&b,''));
%put &path;
The macro variable PATH should be ready to use as %include "&path.codefile.sas";
Thanks ballardw, that is exactly what I was looking for. I only had to make one small modification to get it working. That was to remove the empty quotes:
%let path= %sysfunc(tranwrd(&a,&b,));
tranwrd was replacing the filename with the two adjacent quotes. Removing them made it do what I needed.
Wes
looks like you need to set the current folder, then relative paths will work from there. Double click on the folder/address in the status-bar aat the foot of the SAS environment (assuming that you are not running sas in enterprise guide)
or submit statement
x cd 'required current folder' ;
Peter.
IF you are using the "enhanced" editor in Windows then you can take advantage of environment variables that it sets. That's a big IF for those of us using SAS on other operating systems or who just prefer the normal program editor.
I prefer to use SUBSTR and LENGTH to deal with pulling just the path from the beginning of a string. Using a translate function runs the risk of confusion if some friendly programmer happended to have created a subdirectory that matches your filename.
data _null_;
p1=sysget('sas_execfilepath');
p2=sysget('sas_execfilename');
dir=substr(p1||' ',1,length(p1)-length(p2));
call system('cd ' || quote(trim(dir)));
put 'Running program: ' p1 / 'Switching to directory: ' dir ;
run;
Thanks Tom. That is a good point about the lenght and substring. I'll probably implement something like that.
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!
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.
Ready to level-up your skills? Choose your own adventure.