Hi everyone,
I need to move a set of multiple files file_1, …., file_k with a data null step, so I am applying the following SAS code to achieve this task:
%macro skip(trans_rc,
in,
out,
);
%put **&=trans_rc.**;
%if (&trans_rc. ne 0) %then %do;
data _null_;
rc = filename("_IN_", &in.);
if rc = 0 and fexist("_IN_") then
do;
rc = filename('_OUT_',&out.);
rc = fcopy("_IN_", '_OUT_');
rc = fdelete("_IN_"); rc = filename('_OUT_');
end;
rc = filename("_IN_"); run;
%end;
%mend skip;
%skip(&trans_rc.
,'directory1/file_1'
,'directory2/file_1'
)
In this sense, I have been trying to generalize this code to move all the files file_1, …, file_k (i.e. not only file_1), but I have not been successful.
Any idea?
I do not think you need a macro for that, e.g. (code not tested):
%let indir=directory1;
%let outdir=directory2;
data _null_;
infile cards;
input filetomove $50;
rc = filename("_IN_", "&indir/"!!filetomove);
if rc = 0 and fexist("_IN_") then
do;
rc = filename('_OUT_',"&outdir/"!!filetomove);
rc = fcopy("_IN_", '_OUT_');
if rc=0 then
rc = fdelete("_IN_");
else
stop;
rc = filename('_OUT_');
end;
rc = filename("_IN_");
cards;
file_1
file_2
file_5
;run;
I put in a check, so that if FCOPY returned an error or warning (which you will get with e.g. a truncation), the process will abort.
Or, if your files are actually named with number suffixes, and you know how many (or the maximum number) to move:
%let indir=directory1;
%let outdir=directory2;
%let fileprefix=file_;
%let nooffiles=33;
data _null_;
do _N_=1 to &nooffiles;
rc = filename("_IN_", cats("&indir/&fileprefix",_N_));
if rc = 0 and fexist("_IN_") then do;
rc = filename('_OUT_',cats("&outdir/&fileprefix",_N_));
rc = fcopy("_IN_", '_OUT_');
if rc = 0 then
rc = fdelete("_IN_");
else
stop;
rc = filename('_OUT_');
end;
rc = filename("_IN_");
end;
run;
I know that a simple possibility is to apply multiple times the skip function, for example:
%skip(&trans_rc.
,'directory1/file_1'
,'directory2/file_1'
)
%skip(&trans_rc.
,'directory1/file_k'
,'directory2/file_k'
)
In any case, I am asking for a more compact solution to move in a simple step the entire set of files. For example, one could apply the following simple code by the use of wildcards in Unix:
mv /directory1/file* /directory2
However, I can't use this statement with the sysexec function in SAS, for an issue related to a lack of permissions. That's why I am using the data null step in SAS.
Any idea?
Thanks in advance.
I do not think you need a macro for that, e.g. (code not tested):
%let indir=directory1;
%let outdir=directory2;
data _null_;
infile cards;
input filetomove $50;
rc = filename("_IN_", "&indir/"!!filetomove);
if rc = 0 and fexist("_IN_") then
do;
rc = filename('_OUT_',"&outdir/"!!filetomove);
rc = fcopy("_IN_", '_OUT_');
if rc=0 then
rc = fdelete("_IN_");
else
stop;
rc = filename('_OUT_');
end;
rc = filename("_IN_");
cards;
file_1
file_2
file_5
;run;
I put in a check, so that if FCOPY returned an error or warning (which you will get with e.g. a truncation), the process will abort.
Or, if your files are actually named with number suffixes, and you know how many (or the maximum number) to move:
%let indir=directory1;
%let outdir=directory2;
%let fileprefix=file_;
%let nooffiles=33;
data _null_;
do _N_=1 to &nooffiles;
rc = filename("_IN_", cats("&indir/&fileprefix",_N_));
if rc = 0 and fexist("_IN_") then do;
rc = filename('_OUT_',cats("&outdir/&fileprefix",_N_));
rc = fcopy("_IN_", '_OUT_');
if rc = 0 then
rc = fdelete("_IN_");
else
stop;
rc = filename('_OUT_');
end;
rc = filename("_IN_");
end;
run;
As present above, in this case the copy of the external files is executed only if the variable "trans_rc" is not equal to 0. In this sense, I can't see in your code this possibility.
On the other hand, such a condition can be appropriately implemented with the previous macro, but I just need to generalize it in a more compact form to copy a set of multiple files.
You are right. But you can just put in a line
if &trans_rc then stop;
in the beginning of the datastep
I have noted that your line if &trans_rc then stop; in the beginning of the datastep Works completely fine for the case where trans_rc is not equal to 0, as mentioned above. However, what happens if I want to apply the copy for the case where trans_rc is equal to 0? I have tried to put the line if &trans_rc eq 0 then do: in your example but it does not copy the set of files:
%let indir=directory1;
%let outdir=directory2;
%let fileprefix=file_;
%let nooffiles=33;
data _null_;
if &trans_rc eq 0 then do;
do _N_=1 to &nooffiles;
rc = filename("_IN_", cats("&indir/&fileprefix",_N_));
if rc = 0 and fexist("_IN_") then do;
rc = filename('_OUT_',cats("&outdir/&fileprefix",_N_));
rc = fcopy("_IN_", '_OUT_');
if rc = 0 then
rc = fdelete("_IN_");
else
stop;
rc = filename('_OUT_');
end;
rc = filename("_IN_"); end;
end;
run;
How can I implement your code with the if condition in terms of the specific value of trans_rc?
Thank you very much again.
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.