Einfaches Script schreiben...

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
desputin
Beiträge: 1273
Registriert: 24.04.2015 17:16:34

Einfaches Script schreiben...

Beitrag von desputin » 05.04.2018 13:54:19

Hallo Ihr, ich möchte ein Script schreiben, das das Folgende tut:
  • Alle mbox-Dateien in einem Verzeichnis rekursiv finden
  • Alle diese Dateien kopieren im selben Ordner aber mit der Datei-Endung eml
  • Alle mbox-Dateien in den jeweiligen Ordner in einen Unterordner /alt ablegen.
Die Struktur würde also so aussehen:

Code: Alles auswählen

/ordner/email1.eml
/ordner/alt/email1.mbox
Wie würde ich das machen? hier schon mal einige Fragmente:

Code: Alles auswählen

find -R . -name "*.mbox" 
cp *.eml ./
mkdir alt
mv .*mbox ./alt
oder so ähnlich
Zuletzt geändert von desputin am 05.04.2018 14:41:09, insgesamt 1-mal geändert.
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Einfaches Script schreiben...

Beitrag von uname » 05.04.2018 14:39:44

Vielleicht so:

Code: Alles auswählen

for i in *.mbox;do cp $i alt/;mv $i ${i%.mbox}.eml;done
Also erst kopiert und dann umbenannt.
Direkt aufgerufen in Ordner /ordner. Ich denke die Pfade kannst du selbst anpassen. Für jeden Order einzeln ausführen. Kann man aber auch scripten. Musst evtl. etwas aufpassen. Also erst mit Testdaten probieren.

Insgesamt kann das fehleranfällig sein. Besser wäre wohl vorher alles z. B. mit Debianrsync irgendwo wegzusichern. Falls es eine Art Backup sein soll möchte ich davon abraten. Als einmalige Migration würde ich die alten Dateien auf einer anderen Partition oder externen Platte zuvor sichern.
Zuletzt geändert von uname am 05.04.2018 14:45:27, insgesamt 2-mal geändert.

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: Einfaches Script schreiben...

Beitrag von tobo » 05.04.2018 14:44:06

Erst Schritt 3 /mit Ausnahme von alt/) und dann Schritt 2 (wobei kopieren ersetzt wird durch umbenennen). Nehme mal an, das war eher die Absicht!?

Code: Alles auswählen

find ordner -path ordner/alt -prune -o -type f -name '*.mbox' \( -exec cp {} ordner/alt/ \; \) -a \( -exec rename 's/.mbox$/.eml/' {} \; \)
EDIT: -o richtig gesetzt
Zuletzt geändert von tobo am 05.04.2018 15:44:55, insgesamt 1-mal geändert.

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Einfaches Script schreiben...

Beitrag von uname » 05.04.2018 14:46:41

Ich möchte drigend dazu raten statt "alt" auszuschließen bei find die Option "-maxdepth 1" zu verwenden, falls anwendbar.

Benutzeravatar
desputin
Beiträge: 1273
Registriert: 24.04.2015 17:16:34

Re: Einfaches Script schreiben...

Beitrag von desputin » 05.04.2018 14:51:49

Hallo Ihr, super danke schon mal

@uname: scheint leider noch nicht zu klappen, ich bekomme:

Code: Alles auswählen

cp: das angegebene Ziel 'alt/' ist kein Verzeichnis
mv: das angegebene Ziel 'Abschlag.eml' ist kein Verzeichnis
@tobo: Hier klappt es bei mir auch noch nit:

Code: Alles auswählen

cp: reguläre Datei 'ordner/alt/' kann nicht angelegt werden: Datei oder Verzeichnis nicht gefunden
cp: reguläre Datei 'ordner/alt/' kann nicht angelegt werden: Datei oder Verzeichnis nicht gefunden
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: Einfaches Script schreiben...

Beitrag von tobo » 05.04.2018 14:55:07

uname hat geschrieben: ↑ zum Beitrag ↑
05.04.2018 14:46:41
Ich möchte drigend dazu raten statt "alt" auszuschließen bei find die Option "-maxdepth 1" zu verwenden, falls anwendbar.
Da steht aber rekursiv!?

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: Einfaches Script schreiben...

Beitrag von tobo » 05.04.2018 15:00:47

desputin hat geschrieben: ↑ zum Beitrag ↑
05.04.2018 14:51:49
@tobo: Hier klappt es bei mir auch noch nit:

Code: Alles auswählen

cp: reguläre Datei 'ordner/alt/' kann nicht angelegt werden: Datei oder Verzeichnis nicht gefunden
cp: reguläre Datei 'ordner/alt/' kann nicht angelegt werden: Datei oder Verzeichnis nicht gefunden
Dann leg halt das Verzeichnis an - ordner und alt halt angepasst!?

Code: Alles auswählen

mkdir ordner/alt
Im ganzen Verzeichnisbaum unterhalb von ordner existiert nachher nur ein Verzeichnis alt, oder?

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Einfaches Script schreiben...

Beitrag von uname » 05.04.2018 15:27:06

tobo hat geschrieben:Da steht aber rekursiv!?
Habe ich gelesen und das stimmt. Wenn es rekursiv sein soll über keine Ahnung wie viele Ebenen ist die Idee mit einer Verzeichnistiefe von 1 schlecht. Aber Ordner bei find auszuschließen ist auch nicht ganz trivial und fehleranfällig.

Wie sieht die Struktur tatsächlich aus? Gibt es den Ordner "alt" schon? Poste doch mal die Verzeichnisstruktur an einen Beispiel.

Benutzeravatar
desputin
Beiträge: 1273
Registriert: 24.04.2015 17:16:34

Re: Einfaches Script schreiben...

Beitrag von desputin » 06.04.2018 09:02:29

Die Verzeichnisstruktur sieht in etwa so aus:

Code: Alles auswählen

Ebene 1 - oberster Ordner: Vorgänge
Ebene 2: Unterordner Jahre, also 1990-2015, aber auch ein Paar Ordner die anders heißen wie "Präsentationen" oder "Bestellungen"
Ebene 3: Ordner mit kryptischen Namen wie 000874634 oder 0038626
Ebene 4 - unterste Ordnerebene, in der jeweils nur EINE mbox-Datei liegt - mit Namen wie 0001 0002 0003 0099 0120
Aber eigentlich dürfte die Ordnerstruktur doch egal sein, wenn man den find-Befehlt mit -R ergänzt - und dem Befehl dann mitgibt, den "alt"-Ordner dann jeweils im selben Ordner wie die mbox-Datei zu machen.
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: Einfaches Script schreiben...

Beitrag von RobertDebiannutzer » 09.04.2018 22:03:58

Würde so was funktioniert?
(Nicht (!!!) getestet, keine Garantie!)

Code: Alles auswählen

#!/bin/bash

for i in *; do # 1. Ordnerebene
  cd "$i"
  for i in *; do # 2. Ordnerebene
    cd "$i"
    for i in *; do # 3. Ordnerebene
      cd "$i"
      for i in *; do # 4. Ordnerebene
	cd "$i"
	for i in *; do # Dateien in der 4. Ordnerebene
	  mkdir alt
	  cp "$i" alt
	  mv "$i" "${i%.mbox}.eml"
	done
      done
    done
  done
done
Man könnte sich auch jeweils mit "while" durch "ls -1" loopen, je nachdem. Ich habe nur @unames Vorschlag mal versucht, auf Deine Ordnerstruktur anzuwenden...

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Einfaches Script schreiben...

Beitrag von uname » 10.04.2018 09:58:14

Das mit "cd" würde ich nicht machen. Aktuelle Pfade zu verwenden ist meistens keine gute Idee. Wo ist z. B. das cd ..?

Vielleicht so versuchen. Der aktuell verwendete Pfad ist der Start-Pfad und ändert sich nicht. Besser wäre wohl den Pfad direkt im Befehl zu verdrahten. Aber den Start-Pfad kenne ich nicht.

a.) Schauen, dass die korrekten Dateien ausgewählt werden:

Code: Alles auswählen

find .  -maxdepth 3 -name "*.mbox"
(basiert auf deinen Angaben zu Vorgänge/Jahr/Ordner/Datei, Aufruf im Ordner Vorgänge)

b.) Backup nicht vergessen ;-)

c.) Befehl im Ordner Vorgänge:

Code: Alles auswählen

find .  -maxdepth 3 -name "*.mbox" -exec bash -c 'mkdir -p $(dirname "$1")/alt;cp "$1" $(dirname "$1")/alt;mv -- "$1" "$(dirname "$1")/$(basename "$1" .mbox).eml"' _ '{}' \;
Mit "mkdir -p" wird erreicht, dass beim erneuten Versuch einen Ordner anzulegen kein Fehler ausgegeben wird. Könnte man vielleicht schöner abfangen.
man mkdir hat geschrieben: -p, --parents
no error if existing, make parent directories as needed

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: Einfaches Script schreiben...

Beitrag von RobertDebiannutzer » 10.04.2018 15:18:16

uname hat geschrieben: ↑ zum Beitrag ↑
10.04.2018 09:58:14
Wo ist z. B. das cd ..?
Meinst du mit "aktuellen Pfaden" relative Pfade?
Hast Du dotglob bei Dir in bash aktiviert? Standard bei stretch ist das nämlich nicht und so fallen bei "for i in *" auch keine dotfiles/-dirs an.
Mit aktiviertem dotglob würden aber auch nicht die Einträge "." und ".." anfallen, die gibt es nur bei "ls -a" z.B.
Außerdem kann cd "..", "../", "." und "./" korrekt interpretieren.

Oder beziehst Du Dich auf meinen Vorschlag mit dem while-loop durch "ls -1"? Dann beachte bitte, dass ich nicht "ls -l" meinte, sondern "ls -1". Dabei ist die Zahl Eins die Option und bedeutet nur, dass jeder Eintrag in einer neuen Zeile stehen soll. Dann kann man nämlich auch mit "while read line" damit arbeiten. (Je nach Schriftart kann man Eins und ein kleines L nicht unterscheiden...)
Wobei ... mit ls kann es auch Probleme geben: https://mywiki.wooledge.org/ParsingLs
Je nachdem halt.

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Einfaches Script schreiben...

Beitrag von uname » 10.04.2018 16:31:35

Ich meine eigentlich, dass ich mit Hilfe von Programmen ungern versuche eine Art Programminteraktivität (hier aktuelles Verzeichnis "pwd") nachzustellen. Wenn ich es in meinen Test richtig nachgestellt habe muss mindestens bei dem Beispiel "for ...cd ... done" ein "cd .." folgen.

Vereinfachtes Beispiel. Ordner 2017 und 2018 existieren. Es soll je Ordner eine Datei x angelegt werden:

Code: Alles auswählen

for i in {2017..2018};do cd $i;touch x; cd ..;done
Ingesamt besteht das Risiko, dass bei komplexen Beispielen der Pfad nicht stimmt und Befehle in falschen Ordnern ausgeführt werden.
Wobei wäre ja ganz cool das mal mit "cd" und "cd .." rekursiv [1] zu schreiben. Dann wäre auch die Anzahl der Ebenen egal.

[1] https://de.wikipedia.org/wiki/T%C3%BCrme_von_Hanoi

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: Einfaches Script schreiben...

Beitrag von RobertDebiannutzer » 10.04.2018 16:48:37

Stimmt, ich habe gerade Dein Beispiel getestet. Ohne "cd .." ist mein Vorschlag große Scheiße... :facepalm:
Ich hatte eine Fehlschaltung und bin davon ausgegangen, dass die Befehle in einem bash-loop automatisch in einer subshell ausgeführt werden.

Und wenn ich Dein Beispiel so teste, funktioniert es auch:

Code: Alles auswählen

for i in {2017..2018}; do (cd $i && touch x); done
(habe noch cd und touch mit && verknüpft)

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: Einfaches Script schreiben...

Beitrag von tobo » 10.04.2018 20:43:29

Ich würde folgende Lösung anbieten:

Code: Alles auswählen

find . -path '*/alt' -prune -o -type f -name '*.mbox' -execdir mkdir -p alt \; -execdir cp -a {} alt/ \; -exec rename 's/.mbox$/.eml/' {} \;
Die Vorteile: Es funktioniert, kommt klar mit Leerzeichen in den Pfaden und Dateien, Startverzeichnis und Verzeichnistiefe ist flexibel bzw. irrelevant und es ist direkt ablesbar was passiert.

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: Einfaches Script schreiben...

Beitrag von uname » 11.04.2018 08:40:17

tobo hat geschrieben:

Code: Alles auswählen

find . -path '*/alt' -prune -o -type f -name '*.mbox' -execdir mkdir -p alt \; -execdir cp -a {} alt/ \; -exec rename 's/.mbox$/.eml/' {} \;
Sehr schöne Lösung. Ich sollte doch öfter mal die Manuals lesen.

Benutzeravatar
desputin
Beiträge: 1273
Registriert: 24.04.2015 17:16:34

Re: Einfaches Script schreiben...

Beitrag von desputin » 18.04.2018 09:24:21

Hallo Ihr,

Code: Alles auswählen

find . -path '*/alt' -prune -o -type f -name '*.mbox' -execdir mkdir -p alt \; -execdir cp -a {} alt/ \; -exec rename 's/.mbox$/.eml/' {} \;
Vielen Dank, Tobos Lösung funktioniert schon mal recht gut!
Das Einzige, was aber nicht geht, ist daß danach dei Dateien alle in eml-umbenannt werden (außer natürlich die Dateien im "alt"-Unterordner).

Die Ordner sehen also jetzt so aus:

Code: Alles auswählen

1. Überordner: 0005
2. Datei im Überordner "0005": 001.mbox
3. Unterordner: alt
4. Datei im Unterordner "alt": 001.mbox
Die Datei unter 2. müßte aber 001.eml heißen...
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

tobo
Beiträge: 1964
Registriert: 10.12.2008 10:51:41

Re: Einfaches Script schreiben...

Beitrag von tobo » 18.04.2018 15:56:20

Möglicherweise ist bei dir ein anderes rename aktiv!? Benötigt wird "/usr/bin/file-rename" aus dem Paket "rename". Überprüfen/Setzen kannst du das aktive rename über:

Code: Alles auswählen

# update-alternatives --config rename
Wenn "/usr/bin/file-rename" dort nicht existiert, dann ein

Code: Alles auswählen

# apt-get update && apt-get install rename
einschieben. Das alles ab Jessie ff. Davor hieß das noch irgendwie anders!? Wenn's ganz Not tut, dann macht man es über mv.

Benutzeravatar
desputin
Beiträge: 1273
Registriert: 24.04.2015 17:16:34

Re: Einfaches Script schreiben...

Beitrag von desputin » 19.04.2018 00:10:11

Ah, super. Danke für den Hinweis. Jetzt hat es 1a top funktioniert! Danke!!
https://www.daswirdmanjawohlnochsagenduerfen.de
https://www.neoliberalyse.de - Über die Ökonomisierung aller Lebensbereiche. |

Antworten