PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Files sortieren und packen



Xanthariel
12-08-2009, 15:46
Hallo Forum,

ich habe in einem Verzeichnis sehr viele Dateien mit ähnlichem Namen:

XXX_FEED.YYYYDDDF.DAY.YYYY_MM_DD.gz
oder
ORIG_XXX_FEED.YYYYDDDF.DAY.YYYY_MM_DD.gz

da sich diese Files sehr stark vermehren und ein "ls" nun schon die Zeit überbrückt die man benötigt um einen Kaffee zu holen, sehe ich Handlungsbedarf.

Ziel währe es jeweils alle Dateien eines Jahres und Monats in ein separates Verzeichnis zu verschieben, daß am besten auch gleich mit angelegt werden soll, wenn es bereits besteht nicht mehr.

So wie ich das sehe komme ich hier um "sed" nicht drumherum und bitte daher um Hilfe oder Ideen.

Vielen Dank im Voraus.
Gruß
Xanthariel

zst
12-08-2009, 18:14
Hallo Xanthariel,

ich würde das mit for-Schleife, mkdir, mv und falls nötig auch mit find, aber sed wäre für mich das falsche Werkzeug.
Willst Du uns Deinen Lösungsansatz mal posten?

Gruss zst

DieterH
13-08-2009, 17:24
XXX_FEED.YYYYDDDF.DAY.YYYY_MM_DD.gz
oder
ORIG_XXX_FEED.YYYYDDDF.DAY.YYYY_MM_DD.gz


Unter der Maßgabe, dass die obigen Dateinamen IMMER in vier, durch jeweils einen Punkt getrennte Teile zerfällt, und der dritte Teil IMMER die Form YYYY_MM_DD hat sowie die Dateinamen IMMER auf "*.gz" enden, empfiehlt sich die folgende Vorgehensweise:

1. Erfassen aller Dateinamen in einem Verzeichnis, ${VERZ}, die auf ".gz" enden.
2. Herauslösen ihres Basisnamens
3. Herauslösen der Anteile YYYY, MM und DD aus dem Basisnamen
4. Verschieben der Dateien in das Zielverzeichnis ${ZIEL} (evtl. auf anderer Partition; Ist dort genügend Platz vorhanden?"

for i in `find ${VERZ} -name "*.gz"` ; do
BASENAME=`basename $i`
TEIL3=`echo ${BASENAME} | awk -F "." '{printf("%s",$3) }'`
YYYY=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$1) }'`
MM=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$2) }'`
DD=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$3) }'`

mkdir -p ${ZIEL}/${YYYY}/${MM}/${DD}
mv -i $i ${ZIEL}/${YYYY}/${MM}/${DD}
done

Du kannst "${ZIEL}/" weglassen; dann werden die Dateien in das Verzeichnis verschoben, in dem Du dieses Skript aufrufst. Besser wäre eine klare Vorgabe VOR der for-Schleife:
ZIEL="/abc/def" (oder ähnlich)

Falls eine tagesgenaue Ablage nicht notwendig ist, lasse "/${DD}" bei "mkdir" und "mv -i" einfach weg.

Gruss
Dieter

Xanthariel
14-08-2009, 09:50
Hallo Dieter,

vielen Dank für Deine Mühe.
Dachte ichs mir doch, daß ich ohne SED oder AWK auf keinen grünen Zweig komme.

Da ich noch am Beginn meiner Skripting-Karriere stehe :rolleyes:

Was meinst Du mit Basename?
FEED ???
Das währe die einzige Konstante.
Alles andere verändert sich permanent

Gruß
Xantharielll

DieterH
14-08-2009, 10:24
Da ich noch am Beginn meiner Skripting-Karriere stehe
Wir haben alle mal klein angefangen, Herr Kollege Skriptologe!


Was meinst Du mit Basename?
Jede Datei hat einen Namen und steht irgendwo in einem Verzeichnis. Ein solcher Dateiname ist z.B. /u1/abc/def/Hugo.txt

"Hugo.txt" ist der Basisname, und /u1/abc/def der Verzeichnisname.
Hast Du z.B. MYNAME=/u1/abc/def/Hugo.txt gesetzt,
dann ergibt
`basename ${MYNAME}` den Basisnamen, also "Hugo.txt", und
`dirname ${MYNAME}` den Verzeichnisnamen, also "/u1/abc/def"


FEED ???
Das währe die einzige Konstante.
Alles andere verändert sich permanent

Du möchtest aus Gründen der Übersichtlichkeit die Dateien in Verzeichnisse ablegen, die nach Jahr und Monat geordnet sind. Also muss sich das Skript die Jahreszahl und die Monatszahl herauspicken und mit diesen Werten Verzeichnisse anlegen. Das tut mein Skript.
Falls Du "FEED" mit ins Spiel bringen willst, dann musst Du eben nach "FEED" suchen; ich vermute, die Zeichenkette "XXX" ist ein Platzhalter und kann beliebig lang sein. Mein Skript deckt die Suche nach "FEED" nicht ab. Meines Erachtens ist die Suche nach "FEED" auch gar nicht notwendig, da Du die Dateien geordnet nach Jahr und Monat ablegen willst.

Lass das Skript einfach mal laufen. Am besten, Du erstellst ein Spielverzeichnis, kopierst händisch ein paar Dateien (unterschiedliches Jahr und Monat) hinein, und lässt Dich mal überraschen, was ein gutes Betriebssystem (ich spreche nicht von einem bunten) leistet.

Xanthariel
14-08-2009, 13:01
Das kommt dabei raus.
Es wird auch kein Verzeichnis mit YYYY_MM angelegt.


awk: syntax error near line 1
awk: bailing out near line 1
mv: /app/GB4/dyn/vdps/queues/tk/Feed/Done/VDF_FEED.20092131.Sat.2009_08_01.gz and /app/GB4/dyn/vdps/queues/tk/Feed/Done///VDF_FEED.20092131.Sat.2009_08_01.gz ar
e identical

So wie es aussieht setzt er hier das Ausgeschnittene Verzeichnis nicht um.


VERZ=/app/GB4/dyn/vdps/queues/tk/Feed/Done
ZIEL=/app/GB4/dyn/vdps/queues/tk/Feed/Done
#
for i in `find ${VERZ} -name "*VDF_FEED*"` ; do
BASENAME=`basename $i`
TEIL3=`echo ${BASENAME} | awk -F "." '{printf("%s",$3) }'`
YYYY=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$1) }'`
MM=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$2) }'`
DD=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$3) }'`

mkdir -p ${ZIEL}/${YYYY}/${MM}
mv -i $i ${ZIEL}/${YYYY}/${MM}
done

DieterH
14-08-2009, 13:49
An meinem Arbeitsplatz habe ich nur Windoze und kann daher das Skript unter Linux nicht testen. :(

Folgende Hilfestellungen vorab:

1. Setze beim AUfruf des SKripts vor seinen Namen die Zeichenkette "sh -x "; dadurch siehst du alles was passiert.

2. Falls das noch zu wenig Info liefert, füge hinter jeder gesetzten Variablen ein echo auf deren Inhalt ab:
also z.B. echo ${BASENAME}
oder echo ${TEIL3}
Vor allem der Inhalt von ${TEIL3} ist wichtig, da von ihm alle anderen Variableninhalte abhängen.

Diese Zeilen kannst du dann wieder wegnehmen bzw. auskommentieren, wenn alles prächtig läuft.

3. Die Fehlermeldung "awk ... bailing" bedeutet, dass irgendein Inpterpunktionszeichen nicht richtig gesetzt ist.

4. Die Zeile TEIL3=`echo ${BASENAME} | awk -F "." '{printf("%s",$3) }'`
ändere bitte ab auf:
TEIL3=`echo ${BASENAME} | awk -F "\." '{printf("%s",$3) }'`
(hätte ich Linux hier, könnte ich es sofort testen).

5. Wenn Du ein Verzeichnis YYYY_DD willst, musst du die Zeilen "mkdir ..." und "mv -i" entsprechend ändern. ANstatt "${YYYY}/${MM}" nunmehr "${YYYY}_${MM}"

Xanthariel
14-08-2009, 15:14
Ich habe das nun so umgestellt:


VERZ=/app/GB4/dyn/vdps/queues/tk/Feed/Done
ZIEL=/app/GB4/dyn/vdps/queues/tk/Feed/Done
#
for i in `find ${VERZ} -name "*VDF_FEED*"` ; do
BASENAME=`basename $i`
TEIL3=`echo ${BASENAME} | awk -F "\." '{printf("%s",$3) }'`
YYYY=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$1) }'`
MM=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$2) }'`
DD=`echo ${TEIL3} | awk -F"_" '{ printf("%s",$3) }'`

mkdir -p ${ZIEL}/${YYYY}_${MM}
mv -i $i ${ZIEL}/${YYYY}_${MM}
done

Das Ergebnis:


svpasta:/export/home/t354884=> sh -x clean_Feed.ksh
VERZ=/app/GB4/dyn/vdps/queues/tk/Feed/Done
ZIEL=/app/GB4/dyn/vdps/queues/tk/Feed/Done
+ find /app/GB4/dyn/vdps/queues/tk/Feed/Done -name *VDF_FEED*
+ basename /app/GB4/dyn/vdps/queues/tk/Feed/Done/_/VDF_FEED.20092202.Sat.2009_08_08.gz
BASENAME=VDF_FEED.20092202.Sat.2009_08_08.gz
+ awk -F \. {printf("%s",$3) }
+ echo VDF_FEED.20092202.Sat.2009_08_08.gz
awk: syntax error near line 1
awk: bailing out near line 1
TEIL3=
+ awk -F_ { printf("%s",$1) }
+ echo
YYYY=
+ awk -F_ { printf("%s",$2) }
+ echo
MM=
+ awk -F_ { printf("%s",$3) }
+ echo
DD=
+ mkdir -p /app/GB4/dyn/vdps/queues/tk/Feed/Done/_
+ mv -i /app/GB4/dyn/vdps/queues/tk/Feed/Done/_/VDF_FEED.20092202.Sat.2009_08_08.gz /app/GB4/dyn/vdps/queues/tk/Feed/Done/_
mv: /app/GB4/dyn/vdps/queues/tk/Feed/Done/_/VDF_FEED.20092202.Sat.2009_08_08.gz and /app/GB4/dyn/vdps/queues/tk/Feed/Done/_/VDF_FEED.20092202.Sat.2009_08_08.gz are identical
+ basename /app/GB4/dyn/vdps/queues/tk/Feed/Done/VDF_FEED.20092131.Sat.2009_08_01.gz
BASENAME=VDF_FEED.20092131.Sat.2009_08_01.gz
+ awk -F \. {printf("%s",$3) }
+ echo VDF_FEED.20092131.Sat.2009_08_01.gz
awk: syntax error near line 1
awk: bailing out near line 1
TEIL3=
+ echo
+ awk -F_ { printf("%s",$1) }
YYYY=
+ awk -F_ { printf("%s",$2) }
+ echo
MM=
+ awk -F_ { printf("%s",$3) }
+ echo
DD=
+ mkdir -p /app/GB4/dyn/vdps/queues/tk/Feed/Done/_
+ mv -i /app/GB4/dyn/vdps/queues/tk/Feed/Done/VDF_FEED.20092131.Sat.2009_08_01.gz /app/GB4/dyn/vdps/queues/tk/Feed/Done/_
+ basename /app/GB4/dyn/vdps/queues/tk/Feed/Done/VDF_FEED.20092193.Fri.2009_08_07.gz

DieterH
14-08-2009, 16:37
Ich bin immer noch in der bunten Windoze-Welt ;-)

LÖSUNG 1:
Ersetze die mit "TEIL3=" beginnende Zeile durch:

TEIL3=`echo ${BASENAME} | awk -F " " 'BEGIN{ x[10] = "";}{ split($0,x,"."); printf("%s",x[4]); }'`


LÖSUNG 2 (besser):
Ersetze die mit "TEIL3=" beginnende Zeile durch:

TEIL3=`echo ${BASENAME} | sed -e 's/\./:/g' | awk -F ":" '{ printf("%s",$4); }'`

Hinweis:
In der Zeile "TEIL3=" hätte es rechts von Anfang an heißen müssen "$4" anstatt "$3"; aber das war nicht das eigentliche Problem. Der "awk" mag den Punkt nicht als Feldtrennzeichen.

Bis nachher ...

DieterH
15-08-2009, 11:03
Hallo,

mit der Lösung2 wird TEIL3 korrekt gefüllt und damit auch die Variablen YYYY, MM und DD.

Der Neugliederung Deiner Dateien sollte nichts mehr im Wege stehen.

Gruss
DIeter