Einlesen mehrerer Text-Dateien aus einem Ordner

Hallo,

wie kann ich beim Einlesen von mehreren externen Text-Dateien (aus einem Ordner) (ca. 100) in SAS in EINE SAS-Tabelle den Namen der Text-Datei jeweils ausgeben lassen?

Die SAS-Tabelle sollte nach dem Einlesen folgendermaßen aussehen:

1.Spalte 2.Spalte
Wort1 NameDerTextDatei1
Wort2 NameDerTextDatei1
Wort3 NameDerTextDatei1
.
.
WortN NameDerTextDatei1
Wort1 NameDerTextDatei2
Wort2 NameDerTextDatei2
Wort3 NameDerTextDatei2
.
.
.

Hi, um in eine SAS-Datei die

Hi,
um in eine SAS-Datei die gewünschten Dateinamen auszulesen brauchen sie drei Schritte.
Als erstes lesen sie sich den Pfadnamen aus, speichern die Anzahl der Elemente in diesem Ordner und speichern nur diese, die auch .txt Dateien sind.
Falls mehrere verschiedene Dateien (.xls, .doc uvm.) enthalten sind, selektieren sie einfach nur die .txt Dateien.
Im folgenden habe ich das so umgesetzt!

option mprint;
%macro txt(path);
%let datasetlist=;
%let rc=%sysfunc(filename(dir, &path));
%let d=%sysfunc(dopen(&dir));
%let n=%sysfunc(dnum(&d));
%do i=1 %to &n;
%let file=%sysfunc(dread(&d, &i));
%if %sysfunc(scan(%sysfunc(lowcase(&file)),2,'.')) eq txt %then %do;
data a&i; length datname $200.; nr=&i; datname="&file"; run;
%let help=&datasetlist;
%let datasetlist=&help a&i;
%end;
%end;
%let rc=%sysfunc(dclose(&d));
data ax; set &datasetlist; run;
proc datasets library=work nodetails nolist; delete a1-a%eval(&n-1); run; quit;
%mend txt;
%txt(C:\Test);

Vielleicht ist das etwas für Sie.

Beste Grüße
Niko

Hallo ,ich würde zuerst das

Hallo ,

ich würde zuerst das Verzeichnis auslesen:

%let pfad1="hier steht der pfad";
filename out pipe "dir &pfad1 /B/A:-D";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;

in der Datei Out stehen in der Spalte file die Namen der in Pfad enthaltenen Text-dateien.
Falls es in dem Pfad noch andere Dateien gibt müssten Sie die Spalte file auf die Einträge mit der Endung txt
eingrenzen.
Danach können Sie in einer Makroschleife alle Textdateien einlesen. Etwa wie folgt habe ich es für EXCEL-Tabellen gelöst, wobei ich einen Step zum Einfügen des Namens hinzugefügt habe.
Vielleicht können Sie dieses Programm auf ihren Fall (txt-Dateien) selbst modifizieren:

%macro import(Zieltab=);

%local i anz;

%macro attrn(ds,attrib);

%local dsid rc;

%let dsid=%sysfunc(open(&ds,is));
%if &dsid EQ 0 %then %do;
%put ERROR: (attrn) Dataset &ds not opened due to the following reason:;
%put %sysfunc(sysmsg());
%end;
%else %do;
%sysfunc(attrn(&dsid,&attrib))
%let rc=%sysfunc(close(&dsid));
%end;

%mend;

%macro nobs(ds);
%local nobs;
%let nobs = %attrn(&ds,nobs);
%if &nobs LT 0 %then %let nobs=0;
&nobs
%mend;

%let anz=%nobs(content);
%if &anz ne 0 %then %do;
%do i=1 %to &anz;
DATA _NULL_;
set content (firstobs=&i obs=&i);
Call Execute("PROC IMPORT OUT= WORK.IMP");
Call Execute('DATAFILE="'||"&pfad1\"||compress(file)||'"');
Call Execute('DBMS=EXCEL REPLACE;SHEET="Tabelle1$";GETNAMES=YES; MIXED=YES;SCANTEXT=YES;USEDATE=YES;SCANTIME=YES;RUN;');

/*Für ihr Problem hinzufügen des Namens ggf noch ein lngth Befehl für name setzen!*/
Call Execute("DATA imp; set imp;");
Call Execute("name='"||compress(file)||"';run;");
run;

run;

Proc append base=gesamt data =imp ;
run;

PROC DATASETS lib=WORK NOLIST;
DELETE imp satz;
quit;

%end;

%end;
%mend;
%import;

Hallo, erstmal vielen Dank

Hallo, erstmal vielen Dank für Ihre Hilfe.
Es ist mir aber ehrlich gesagt zu kompliziert :(
Vielleicht kann man alle Text-dateien aus dem Ordner in unterschiedliche SAS-Tabellen importieren?
Ich vermute, danach wäre es etwas einfacher, die Namen von den Dateien einzulesen.

noch einfacher

Hallo,

so geht es auch mit Sonderzeichen und Leerzeichen im Pfad.
Dies Beispiel funktioniert unter Windows. Die temporäre Datei ist nötig, da das INFILE Statement keine Option Encoding verträgt, wenn man als Infile eine PIPE verwendet. Dann muss man erst die Sonderzeichen ersetzen. Da die Macrovariablen nur in Anführungszeichen aufgelöst werden, aber nicht in Hochkommatas, müssen die doppelten Anführungszeichen beim X - Command sein.

/* Den Pfad definieren */
%LET PFAD =.\Eigene Dateien;
/*Temporäre Datei definieren */
%LET TEMPDIR = C:\temp\dir.txt;
/*
Dateiliste in Temporäre Datei einlesen
Pfade müssen in Anführungszeichen gesetzt werden
wenn sie Leerzeichen enthalten
Anführungszeichen müssen doppelt angegeben werden, wenn
sie in Anführungszeichen stehen

*/
OPTION NOXWAIT;
X "dir ""&PFAD.\*.txt"" /B /A:-D > ""&TempDir.""" ;

/* Einlesen der temporären Datei */
DATA Dateien;
FORMAT File $256.;
INFILE
"&TempDir."
LENGTH = filelen /* für $Varying. */
/*
DOS verendet einen anderen Zeichensatz als Windows
Wenn die Dateinamen Sonderzeichen enthalten
gibt es sonst Probleme
*/
ENCODING = PCOEM
;
INPUT File $VARYING. filelen;
RUN;

/* Löschen der temporären Datei */
X "delete ""&TempDir.""";

/* Trennzeichen Definieren */
%LET trenner = ' ,;.?!"%&/\=$§+*~#|<>:@()[]{}^° '; /* z. B. */
/* Einlesen aus den Dateien */
DATA woerter;
LENGTH Datei wort $256;
SET dateien;
/* Vollständigen Pfad erzeugen */
Datei=CATS("&PFAD.\", file);

INFILE
Datei
FILEVAR = Datei
DLM = &Trenner.
/* Zu diesem Label wird am Dateiende gesprungen */
EOF = ende
/* Pufferlänge für eine Zeile */
LRECL = 32767
;
/* Datensatz für Datensatz aus Textdatei auslesen*/
DO WHILE (1); /* immer wahr */
Input wort@@; /* Einlesen eines Worts */
/* ... weitere Programmschritte */
OUTPUT; /* Ausgeben des Datensatzes */
END;
/*
Hierhin springt das Programm
wenn das Dateiende erreicht ist
*/
ENDE:
RUN;

Innerhalb der Schleife stehen dann dieselben Befehle, wie wenn man eine einzelne Datei einlesen würde (siehe vorige Frage von Ihnen).

schöne Grüße

Jan

Einfacher So?:

Hallo ,

vielleicht probieren Sie folgendes Makro. Bitte bei dem Pfad und den Namen der Textdateien keine Sonderzeichen und Leerzeichen verwenden sonst sind Anpassungen nötig:

%let pfad1=J:\zzz\bbb\text;
filename out pipe "dir &pfad1 /B/A:-D";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;

%macro import(Zieltab=);
Proc SQL noprint;
select distinct file into :lst
separated by "#"
from content;
quit;

%let i=1;
%let dat=%scan(&lst,&i,#);
%do %while (&dat ne );
data WORK._t&i ; ;
%let _EFIERR_ = 0; /* set the ERROR detection macro variable */
infile "&pfad1.\&dat." MISSOVER DSD lrecl=32767 firstobs=2 ;
informat u $1. ;
format u $1. ;
input
u $
;
if _ERROR_ then call symputx('_EFIERR_',1); /* set ERROR detection macro variable */
run;

Data _T&i;
set _T&i;
length name $32.;
name="&dat";
run;
%let i=%eval(&i+1);
%let dat=%scan(&lst,&i,#);
%end;

%mend;
%import;

funktioniert das Makro auch unter UNIX ?

... hab das mal versucht.

%let pfad1=/p/.../tag/;
filename out pipe "dir &pfad1 /B/A:-D";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;

und bekomme "/bin/ksh: dir: not found".

Ich würde gerne ein Verzeichnis auslesen und zwar nur csv files, die mit bestimmten Namen beginnen. Da ich tgl. eine Datei erhalten, wollte ich dann jeweils immer die letzte importieren. dafür würde ich das Verzeichnis auslesen absteigend sortieren und dann die letzte datei importieren.

Nur das Auslesen des UNIX Pfades klappt nicht. Hat jemand noch eine Idee ?

Gruß, Sven

hab den Befehl gefunden...

LS

%let pfad1=/p/b29y/sp0e/spdswork/transfer/tag/;
filename out pipe "ls &pfad1";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;

Danach nur noch sortieren und den ersten Wert nehmen.

Sortieren, aber wonach

Hallo,
wonach soll denn sortiert werden?
Wenn es heißt wollte ich dann jeweils immer die letzte importieren, dann denke ich bei die letzte an die jüngste Datei. Also müßte dann nach Datei-Datum sortiert werden ... Bloß: Das fehlt in den eingelesenen Daten ... :-/

Oder man läßt sich die Date-Liste vom Betriebssystem nach Zeit sortiert geben:

%let pfad1=/usr/sas;
filename out pipe "ls -t &pfad1"; /* ls-Befehl mit option -t */
/* -t Sorts by time stamp (latest first) instead of by name */
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;
data _null_;
set content;
if _N_ eq 1 then do;
call symput("Letzte", file);
end;
run;
%put INFO: Letzte=&Letzte.;

Oder man sortiert selbst, dann benötigt man aber auch das Datei-Änderungsdatum und muß den ls-Befehl entsprechend erweitern:

%let pfad1=/usr/sas;
filename out pipe "ls -l &pfad1"; /* ls-Befehl mit option -l */
/* -l Lists in long format, giving mode, ... size in */
/* bytes and time of last modification for each file */
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;

Das Sortieren gestaltet sich etwas mühsam, denn die Ausgabe in der SAS-Base-Variable file sieht z.B. so aus:

-rw-rw-r--   1 sas      sasgrp    205789 Sep 15 01:10 wekausl2kop.log

Eine Anmerkung noch zum ursprünglichen Beispiel aus dem Beitrag von en-trust vom 15. Oktober 2009, 09:06.
Der ls-Befehl sollte für solche Einsatz-Fälle immer mit der Option -1 verwendet werden, denn ohne diese Option gibt der ls-Befehl platzsparend mehrere Datei-Namen in einer Zeile aus, ungefähr so:

> ls
_tmpk.tmp    awd.doc      reorder.sas  SSN.log      VGS
_tmpp.tmp    readin.sas   sasuser      SSN.log.lck  xxxxx
>

Mit ls -1 sieht es so aus:

> ls -1
_tmpk.tmp
_tmpp.tmp
awd.doc
readin.sas
reorder.sas
sasuser
SSN.log
SSN.log.lck
VGS
xxxxx
>

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)