Is it possible to FTP a ZIP folder from a SAS EG server session? - sas

I am working on SAS server and I am able to successfully create a ZIP in my remote SAS user library by using ods commands. SAS shows the ZIP in my /sascode/user library and it is populated with 500kb of data using the following code:
filename csv_file "/sascode/user/file.csv"
ods package(newzip) open nopf;
ods package(newzip) add file=csv_file;
ods package(newzip) publish archive
properties(
archive_name="file.zip"
archive_path="/sascode/user/"
);
ods package(newzip) close;
When I use a simple pipe to unzip the folder only 1 record is returned and it has the value of 1:
filename x pipe "unzip 'sascode/user/file.zip'
data _null_;
infile x;
input;
put _infile_;
run;
So basically, there is not data inside according to SAS... even though SAS created the ZIP. Therefore, it is expected that when I FTP the file, the resulting ZIP is either empty or corrupt no matter what I try.
To FTP the file to a shared drive I have tried:
ods listing close ;
/* Use the Pipe command to pipe all of the body files generated and */
/* all of the supporting files. */
filename zipit pipe 'zip file.csv';
data _null_;
file zipit;
put 'The will zip the files';
run;
filename zipit clear;
/* FTP the zipped file created */
filename moveit ftp '~my-user-id/test.zip' BINARY
host='node.company.com' prompt debug
user='my-user-id'
pass='abc123';
data _null_;
file moveit;
put;
run;
ods listing;
recfm=N is not a valid option in the above filename moveit portion of the code. This code successfully FTP's the ZIP, but it is corrupted.
data _null_;
infile zip_file;
file ftp_file;
input;
put _infile_;
With the proper filename ftp commands of course. The ZIP folder appears in the expected shared drive folder with either 0 or 1kb of data compared to the 500kb present in my SAS user data folder.
I have also tried many variations of a null datastep with infile/file and playing around binary/nybte/recfm options to no avail.
Is what I am trying to do even possible? Any ideas would be much appreciated.

unzip will extract files from the archive and create them in the current folder.
Use unzip -l to pipe the archive content listing to stdout for reading via infile.
Use unzip -p to pipe the binary contents to stdout (not useful).
If pipe is not available to your SAS session, use the zip file engine, dopen/dread/mopen/input/put to unzip the archive contents.

If you want use SAS to copy a file, you need to use file I/O function. The following is an example to copy C:\Profiles\XLab\PHSUG_2022.rar to C:\Profiles\new.rar.
filename _from_ "C:\Profiles\XLab\PHSUG_2022.rar" recfm=n;
filename _to_ "C:\Profiles\new.rar" recfm=n;
data _null_;
fid=fopen('_from_');
if fid then do;
fcopy=fcopy('_from_','_to_');
if fcopy=0 then putlog 'NOTE: Copy successed.';
else do; *Put error message if copy failed;
e=sysmsg();
putlog e;
end;
fid=fclose(fid);
end;
run;

Related

Sas entreprise équivalent of x’cp …. …’

Is there an function which can copy a file from one folder to another one in sas enterprise? I know it’s the command cp in an Unix environment. I’m searching a solution which doesn’t make me change the default settings in sas.
Use the FCOPY() function.
Example from documentation:
/* Set MSGLEVEL to I to write messages from FCOPY to the log. */
options msglevel=i;
filename src 'source.txt';
filename dest 'destination.txt';
/* Create an example file to copy. */
data _null_;
file src;
do i=1, 2105, 300312, 400501;
put i:words256.;
end;
run;
/* Copy the records of SRC to DEST. */
data _null_;
length msg $ 384;
rc=fcopy('src', 'dest');
if rc=0 then
put 'Copied SRC to DEST.';
else do;
msg=sysmsg();
put rc= msg=;
end;
run;
If your SAS Session is locked down, you could try to use the RENAME() function.
If the SAS session in which you are specifying the FILEEXIST function is in a locked-down state, and the pathname specified in the function has not been added to the lockdown path list, then the function will fail and a file access error related to the locked-down data will not be generated in the SAS log unless you specify the SYSMSG function.
Don't get disturbed by the FILEEXIST, the documentation team forgot to change the function name when copy pasting the description...
data _null_;
rc = rename("\\path\to\file.csv",
"\\another\path\file.csv",
"file");
put rc=;
run;
If your platform administrator enabled the x command, you can just pass the command to your operating system.
x 'cp /from/path/data.file /to/path';
or with some typical macro variables
x "cp &fromPath/&dataFile &toPath";
Otherwise, it is impossible.

Convert SAS7BCAT into DATASET

I try to open a SAS CATALOG file (SAS7BCAT) with SAS ENTERPRISE GUIDE. And I receive always this message :
ERROR: File DIFTFMT.FORMATSX64.CATALOG was created for a different
operating system.
Who could convert my CATALOG format in a DATASET format? Like this I will be able to create my own catalog!
Thank you in advance.
For your information : The operating system used to create this CATALOG file is 9.0401B0X64_S08R2
The code which retunrs the error :
/* SAS CODE BEGIN*/
libname diftfmt '/ec/local/sas/data/training/OrionStar/orfmt';
options fmtsearch=(diftfmt);
PROC FORMAT library=diftfmt.formatsx64 fmtlib;
RUN;
/* SAS CODE END*/
The code to find the operating system:
/* SAS CODE BEGIN*/
filename test
"/ec/local/sas/data/training/OrionStar/orfmt/formatsx64.sas7bcat";
DATA enc (keep=encoding);
length encoding $ 20;
infile test truncover scanover;
input #'9.0' enc $14.;
encoding = '9.0' || enc;
RUN;
/* SAS CODE END*/

SAS PROC EXPORT to secure location

I am trying to store a tabdelimited file to a shared folder that requires a login (username + password).
When I have opened (and logged in) to the location via windows explorer, PROC EXPORT runs without errors.
If I run it without having logged in during the windows session, I get a generic I/O error in the log.
Is there a way to add my login and password to the PROC EXPORT procedure?
There is nothing in proc export that will allow this. I'd suggest running a windows command to open the share before the proc export, such as:
X "net use \\server\share /user:test /password:test"
or
filename mypipe pipe "net use \\server\share /user:test /password:test";
data _null_; infile mypipe; input; list; run;
filename mypipe close;
(credit - https://serverfault.com/questions/580369/windows-shares-via-command-line-with-user-pass-without-mapping-the-drive)

SAS Compare Two Text Files (Unix / Windows)

I need to compare two text files (in different directories) to see if they are different (a binary result is fine). Given a dataset such as the one below, is this possible within a datastep?
Pathname
c:\one\text1.txt
c:\two\text1.txt
c:\one\text2.txt
c:\two\text2.txt
Alternatively, macro code would be fine! Checksum is a possibility, I need the code to run in both windows & unix.
Pass it to the command line (via a pipe fileref)
In Windows, use the 'comp' command.
In Unix, use the 'diff' command.
Thanks to Chris J - this worked for me:
%let root=%sysfunc(pathname(work));
data;
file "&root.\x.txt";
put 'xxx';
data;
file "&root.\x2.txt";
put 'xx x';
filename x pipe "diff &root.\x.txt &root.\x2.txt ";
data;
infile x;
input x $1000.;
run;

Compiling SAS SCL code programmatically

Is there a programmatic way of compiling SAS 9.1.3 SCL code (N.B. not ordinary SAS code) in Windows? The only way I have found of doing it involves using the SAS GUI: we have a Perl script which sends keystrokes to the UI. While this works (sort of), it's ugly and error-prone, and is too fragile to add to our automated build script.
EDIT: My original question was probably somewhat unclear. I am aware of proc build; my problem is getting some plain text into the SAS catalogue as an SCL entry in the first place.
I found this to be a chicken-and-egg kind of problem. I found that it is only possible to get plain text into an SCL entry, by using an already existing SCL entry...
I have a setup, where I read and write SCL code in Catalog entries, from and to plain text files. I use this for revision control purposes (CVS).
While CVS is mostly used for plain text code, it can also handle binary files. Thus I have made an SCL entry (called FILE2SCL), that can import plain text into other SCL entries. I have then PROC CPORT'ed this SCL entry to a binary file, and checked it into CVS.
This way, I can always programmatically fetch this SCL entry from the CPORT file, and use this SCL entry to import SCL code from plain text into other SCL entries. Afterwards I can use PROC BUILD to compile the SCL entry, exactly like you mention yourself.
My FILE2SCL entry looks like this:
INIT:
/***************************************************************/
/* */
/* Call this SCL like this: */
/* %let srcFile=D:\work\dummy.scl; */
/* %let dstEntry=WORK.NEW.DUMMY.SCL; */
/* proc display catalog=work.cat.file2scl.scl; */
/* run; */
/* */
/***************************************************************/
length Rc 8;
length theFile $ 200;
length theEntry $ 128;
theFile=symget('SRCFILE'); * Source file *;
theEntry=symget('DSTENTRY'); * Destination entry *;
* Assign filename *;
Rc=filename('temp',theFile);
* Include external file into preview buffer *;
Rc=PREVIEW('INCLUDE','temp');
* Save contents of preview buffer to SCL entry *;
Rc=PREVIEW('SAVE',theEntry);
Rc=PREVIEW('CLEAR');
Rc=PREVIEW('CLOSE');
* Deassign filename *;
Rc=filename('temp','');
return;
The comment explains how to use it:
Start with setting a SAS macro variable, "srcFile", to contain the path to your SCL source code file, and another macro variable, "dstEntry" to contain the entry-path to where you want your SCL entry to be. Then PROC DISPLAY the FILE2SCL entry, and it will import your SCL source code into the specified SCL entry, and you can then compile it afterwards by using PROC BUILD.
Also, you can possibly check out using Eclipse and the ESLink plugin. It was designed specifically for this purpose (keeping SCL code in regular files for version control with the capability to compile into a catalog).