By excecuting the following code i am facing the error marked in red:
%Macro read;
%let fileinfo=codedir;
%DO I = 1 %TO &maxlib;
DATA test3;
Pipe_command = "dir /s /b "||'"'||&&lib&I||'"';
PUT PIPE_COMMAND=;
CALL SYMPUT ('Pipe_command', Pipe_command);
RUN;
%PUT &Pipe_command;
%sysfunc (FILENAME (fileinfo,%str (&Pipe_Command)),pipe);
%END;
%Mend read;
%read;
All lines are working fine except
%sysfunc (FILENAME (fileinfo,%nrbquote (&Pipe_Command)),pipe);
The error is:
SYMBOLGEN: Macro variable PIPE_COMMAND resolves to dir /s /b "C:\sametime"
ERROR: Format name PIPE not found or the width and/or decimal specified for the format used are out
of range.
MPRINT(READ): 20017;
MLOGIC(READ): %DO loop index variable I is now 2; loop will not iterate again.
MLOGIC(READ): Ending execution.
NOTE: Line generated by the macro function "SYSFUNC".
1 20017
-----
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
I need a outfile named as CODEDIR containg the output of line ,%str (&Pipe_Command).
Need your suggestions to resolve the issue.
Thanks in advance..
%sysfunc (FILENAME (fileinfo,%str (&Pipe_Command)),pipe);
I think the there should be just one closing brace after &Pipe_Command.
%sysfunc (FILENAME (fileinfo,%str (&Pipe_Command) ,pipe));
is that NRBQUOTE or STR?
looks like NRBQUOTE has "eaten" one of those close-brackets.
Ani
the mixture of data step and macro environment may be getting in the way here.
The purpose seems to be to invoke filename functions, each establishing a pipe to list files in a folder and the subfolders under that.
One caution :- only one fileref is used, so either more processing is to be performed between the loops or a counter suffix is needed on the fileref that will be assigned.
I would suggest :-
1
use the data step to invoke the filename function - as it is function designed to be invoked in data step.
2
in the data step, loop i=1 to maxlib
3
As appending a suffix to the fileref codedir will limit the list of code libraries to 9, abbreviate that to "code" (the context indicates it is a "dir")
4
insert some code (call execute?) to do something with the fileref
Here is my interpretation of a possible solution:
%Macro codedir( folders /* delimited list of folders */
, delimiter= # /* delimiter between folders */
, out= folder_list /* data set to hold list of folders and RC from filename function */
, files= files_list /* data set to hold list of files found in folders */
) ;
proc delete data= &files ;
run ;
DATA &out (keep= rc fileref folder ) ; ;
retain Pipe_c 'dir /s /b ' ;
length folder $1000 fileref $8 ;
maxlib = countw( "&folders", "&delimiter" ) ;
do i=1 to maxlib ;
folder = scan( "&folders" , i , "&delimiter" ) ;
fileref= 'code' !! put(i,4.-L) ;
rc= FILENAME( fileref
, quote( Pipe_c !! quote( trim( folder ) ) )
, 'pipe' ) ;
output ;
* submit for execution later, code to collect list of files in code folders;
call execute( 'data a ;' ) ;
call execute( ' infile code' !! put( i, 4.-L ) ) ;
call execute( '; input line $char1000. ; run; ' ) ;
call execute( 'proc append base=&files ; run ;' ) ;
end ;
stop ;
RUN;
%Mend codedir ;
option compress=yes ;
%codedir( savian#ArtC.book1)
(tested OK)
"Savian" and "ArtC.book1" are folders under the "current folder" of my SAS session
peterC
Hi Peter,
Thanks for your inputs!
But I have no scope to pass parameters in the code. Actually I just need to produce a output file named as codedir which will contain the result of dir /s /b "C:\Smaetime"
C:\Smaetime: is the local path of my system.
DATA test3
Pipe_command = "'dir /s /b "||'"'||&&lib&I||'"'||"'";
PUT PIPE_COMMAND=;
CALL SYMPUT ('Pipe_command', Pipe_command);
RUN;
%PUT &Pipe_command;
FILENAME codedir pipe &Pipe_Command;
When I use FILENAME codedir pipe &Pipe_Command;
Its not working. This is why I tried the following way:
%Macro read;
%let fileinfo=codedir;
%DO I = 1 %TO &maxlib;
DATA test3;
Pipe_command = "dir /s /b "||'"'||&&lib&I||'"';
PUT PIPE_COMMAND=;
CALL SYMPUT ('Pipe_command', Pipe_command);
RUN;
%PUT &Pipe_command;
%sysfunc (FILENAME (fileinfo,%str (&Pipe_Command)),pipe);
%END;
%Mend read;
%read;
And here I face the error:
SYMBOLGEN: Macro variable PIPE_COMMAND resolves to dir /s /b "C:\sametime"
ERROR: Format name PIPE not found or the width and/or decimal specified for the format used are out
of range.
MPRINT(READ): 20017;
MLOGIC(READ): %DO loop index variable I is now 2; loop will not iterate again.
MLOGIC(READ): Ending execution.
NOTE: Line generated by the macro function "SYSFUNC".
1 20017
-----
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
My concern is not in the maxlib count or anyother count. I just need the output of the dir /s /b "C:\Smaetime" in a file and then i'll use this a file as a input.
Thanks in advance
then it becomes simpler
just the data step to create and run a step to use the fileref creating sas table "work.filelist"
replace C:\temp with your folder
DATA _null_ ;
length fileref $8 ;
retain Pipe_c 'dir /s /b "C:\temp" ' fileref 'codedir' ;
rc= FILENAME( fileref
, quote( Pipe_c )
, 'pipe' ) ;
* submit for execution later, code to collect list of files in code folders;
call execute( 'data filelist( compress=yes );' ) ;
call execute( ' infile codedir lrecl=1000 ;' ) ;
call execute( '; input line $char1000. ; run; ' ) ;
call execute( 'FILENAME CODEDIR ;' ); * to release the fileref ;
stop ;
RUN;
Hi Peter,,
Thanks again for your help and it really good. But when I move to the next step :
DATA Search_Obj_Names (KEEP=Srch_File Program_Nam Path);
EOFC = 0;
INFILE codedir MISSOVER TRUNCOVER END=EOFC ;
RETAIN cnt 0;
INPUT @ 1 Srch_File $256.
;
cnt + 1;
Backward = REVERSE(TRIM(srch_file));
last_slash = INDEX(Backward, '\');
IF last_slash = 0 THEN
last_slash = INDEX(Backward, '/');
IF Last_slash = 0 THEN
DO;
Program = Srch_file;
Path = Srch_file;
END;
ELSE
DO;
Program_Nam = REVERSE(SUBSTR(Backward, 1, Last_slash - 1));
Path = STRIP(REVERSE(SUBSTR(backward, Last_slash)));
END;
S7 = INDEX (Program_Nam, 'sas7bdat');
IF S7 THEN;
ELSE
OUTPUT;
RUN;
It throws an error :
ERROR: No logical assign for filename CODEDIR.
Please look into this and put your inputs plz.
Thanks in advance
I had half anticipated what you wanted, and loaded the physical names - then released CODEDIR
Either you you remove the last call execute() statement
call execute( 'FILENAME CODEDIR ;' ); * to release the fileref ;
or adapt your data step.
CODEDIR returns the bare path and filename.
The following code works onn WIN and UNIX platforms, but not on zOS and probably not on VMS
I would suggest you adapt your process.
Parsing the lines returned by CODEDIR might be easier with the scan() function
filename = scan( line, -1, '/\' ) ; * neither / not \ will appear in filenames you are concerned about;
filetype = scan( filename, -1, '.' ) ;
if filetype = 'sas7bdat' then SAS_ds_name = upcase( scan( filename, 1, '.' )) ;
else
if lowcase(filetype) = 'sas' then prog_name = filename ;
not sure why you identify sas7bdat and then ignore them..
data ds_and_progs ;
set filelist ;
length filename $100 filetype $8 prog_name $40 sas_ds_name $32 filepath $1000;
filename = scan( line, -1, '/\' ) ;
* neither / not \ will appear in filenames you are concerned about;
filetype = scan( filename, -1, '.' ) ;
if filetype = 'sas7bdat' then
SAS_ds_name = upcase( scan( filename, 1, '.' )) ;
else
if lowcase(filetype) = 'sas' then
prog_name = filename ;
else delete ;
filepath = substr( line, 1, length(line) - length( filename) -1 ) ;
run ;
.
pick the results you want
Please try this
FILENAME CODEDIR PIPE "dir /s /d c:\sametime";
DATA DSN;
INFILE CODEDIR TRUNCOVER;
INPUT VAR1 $ 50.;
.....
SAS STATEMENTS
.....
RUN;
you can use this CODEDIR anywhere in your program.
Hope this helps
Thanks
Dhanasekaran R
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.