SAS Programm zum Kopieren externer Dateien ohne Systembefehle aber inkl. Wildcards

15. Januar 2024

Haben Sie schon einmal versucht beliebige Dateien mit Hilfe von SAS-Code zu kopieren? Oftmals werden hierzu Methoden verwendet die Systembefehle wie %sysexec, system oder X verwenden.

Was aber tun wenn diese Befehle aus Sicherheitsgründen gesperrt sind? Dann kommt in der Regel bei der Fehlermeldung

SAS Programm zum Kopieren externer Dateien ohne Systembefehle aber inkl. Wildcards Oliver Pitzius

an.

Das kopieren einzelner Dateien ist relativ leicht mit Hilfe von Fcopy möglich. Was aber wenn man auch eine Liste von Dateien kopieren möchte und dazu auch den * als Wildcard verwenden möchte.

Hierzu habe ich folgendes Makro geschrieben, dass für Windowssysteme gedacht ist.

Makro Filecopy 

%MACRO filecopy(indir, outdir, filedesc);
	/* * Wildcard wird in PROC SQL Wildcard % umgewandelt */
	DATA TEST2;
		filedesc = "&filedesc";

		IF FIND(filedesc,"*") THEN
			DO;
				filedesc =  TRANWRD(filedesc,"*","%");
				CALL SYMPUTX ("filedesc",CATS("'",filedesc,"'"));
			END;
	RUN;

	data DIRCONTENTS;
		keep Verzeichnis Dateiname Endung InNameUndPfad OutNameUndPfad;
		length Verzeichnis $40 fref $8 Dateiname $80 Endung $30
			PfadundName OutNameUndPfad $200 
		;
		rc = filename(fref, "&indir");

		if rc = 0 then
			do;
				did = dopen(fref);
				rc = filename(fref);
			end;
		else
			do;
				length msg $200.;
				msg = sysmsg();
				put msg=;
				did = .;
			end;

		if did <= 0 then
			putlog 'ERR' 'OR: Unable to open directory.';
		dnum = dnum(did);

		do i = 1 to dnum;
			Verzeichnis = "&indir";
			Dateiname = dread(did, i);
			Endung = LOWCASE(SUBSTR(Dateiname,Find(Dateiname,".")+1));

			/* Ausgabe falls Eintrag eine Datei ist. Falls eintrag ein Unterverzeichnis, nicht ausgeben.*/
			fid = mopen(did, Dateiname);

			/* In- und Outputdateien */
			InNameUndPfad =  "&indir"||STRIP(Dateiname);
			OutNameUndPfad = "&outdir"||STRIP(Dateiname);

			if fid > 0 then
				output;
		end;

		rc = dclose(did);
		;
	run;

	/* Filterung ggf. mit SQL Wildcards */
	PROC SQL NOWARN;
		CREATE TABLE COPYLIST
			AS SELECT 
				*
			FROM DIRCONTENTS
				WHERE Dateiname LIKE &filedesc;
	RUN;

	DATA _NULL_;
		SET COPYLIST END=eof;
		CALL SYMPUTX("INFI"||LEFT(_N_),InNameUndPfad);
		CALL SYMPUTX("OUTFI"||LEFT(_N_),OutNameUndPfad);

		IF eof THEN
			CALL SYMPUTX("ANZAHL_DATEIEN",_N_);
	RUN;

	%PUT NOTE: Anzahl zu kopierender Dateien: &ANZAHL_DATEIEN..;

	%DO i=1 %TO &ANZAHL_DATEIEN;
		%PUT NOTE: &i.. Datei &&INFI&i wird kopiert.;
filename _bcin "&&infi&i" recfm=n 
/* RECFM=N needed for a binary copy */;
		filename _bcout "&&outfi&i" recfm=n;

		data _null_;
			length msg $ 384;
			rc=fcopy('_bcin', '_bcout');

			if rc=0 then
				put "Copied &&infi&i to &&outfi&i..";
			else
				do;
					msg=sysmsg();
					put rc= msg=;
				end;
		run;

	%END;
%MEND;

Beispielaufrufe

%filecopy(C:\dir\, C:\dir\Subdir1\,CC_inp_23_2023_02.csv);
%filecopy(C:\dir\, C:\dir\Subdir1\,CC_inp_*_2023_*.csv);
%filecopy(C:\dir\, C:\dir\Subdir1\,*.xls*);
%filecopy(C:\dir\, C:\dir\Subdir1\,*.pdf);
cross-circleCookie Consent Banner von Real Cookie Banner