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.
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.