PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Verzeichnisname ausschneiden und in Variable schreiben



Radis
11-05-2007, 21:43
Hallo,

ich versuche gerade, ein find-Script zu schreiben, dass Dateien ab einer bestimmten mtime findet und per mv in einen Müll-Ordner verschiebt - inklusive Verzeichnisstruktur.

Bsp: Dateien liegen im Ordner "/data/public" und sollen nach "/data/müll" verschoben werden.
Das Ganze sieht dann etwa so aus (ausm Stegreif, also durchaus noch mit Fehlern):



#!/bin/sh
# ins Verzeichnis wechseln
cd /data/public
# find-Orgie loslassen
find . -type f -atime -420 | while read $file; do
# './' am Anfang weg:
file=${file#./}
# und dateiname wegschneiden: alles ab dem und inklusive dem letzten "/" durch nix ersetzen:
$directory=$(echo $file | sed s/^*[^\/]//)
# hier noch eine Überprüfung ob das Verzeichnis schon existiert:
#...to come
#Verzeichnis erstellen
mkdir -p ../müll/$directory
# und datei reinmoven
mv $datei ../müll/$directory/
# Prüfung: wenn altes Verzeichnis leer, dann gleich rmdir
# ...to come
done;

los.

Aber das "sed" krieg ich mit meiner bescheidenen Regex-Erfahrung einfach nicht hin. Wenn echo an sed bspw "./unterverz1/unterverz2/dateiname" übergibt, soll der String "unterverz1/unterverz2" generiert werden, damit ich die Verzeichnisstruktur im Müll-Ordner abbilden kann.

Ich wär dankbar wenn jemand helfen könnte der von Regex mehr versteht als ich...

jan61
11-05-2007, 23:00
Moin,
ich habe mal meine Änderungen direkt im Code reingeschrieben und kommentiert:


#!/bin/sh
# ins Verzeichnis wechseln
cd /data/public
# find-Orgie loslassen
# jan61: ups - du wolltest doch mtime prüfen, oder?
# du suchst hier dateien, auf die vor _weniger_ als 420 tagen
# zugegriffen wurde (atime) - wolltest du das?
# und: Zuweisung (read) nie mit $
find . -type f -atime -420 | while read file; do
# './' am Anfang weg:
# jan61: das wuerde ich weglassen, ist unnoetig (s. u.)
# file=${file#./}
# und dateiname wegschneiden: alles ab dem und inklusive dem
# letzten "/" durch nix ersetzen:
# jan61: so sollte es laufen - btw: Zuweisung nie mit $
directory=$(echo "$file" | sed 's/\/[^/]*$//')
# jan61: mit der Änderung oben (./ nicht wegschnippeln) kommt hier immer was
# Sinnvolles an, mindestens "." - sonst:
# jan61: allerdings liefert das fuer direkt in /data/public liegende
# Dateien den Dateinamen - auch nicht schoen - besser ist:
directory="`dirname \"$file\"`"
# hier noch eine Überprüfung ob das Verzeichnis schon existiert:
#...to come
# jan61: nicht noetig bei mkdir -p
#Verzeichnis erstellen
mkdir -p "../müll/$directory"
# und datei reinmoven
# jan61: aehm - du hast kein $datei - das ding heisst $file
mv "$file" "../müll/$directory/"
# Prüfung: wenn altes Verzeichnis leer, dann gleich rmdir
# ...to come
# jan61 - wuerde ich spaeter ueber einen einzigen find machen
done
# jan61: leere Verzeichnisse wegputzen
find /data/public -mindepth 1 -type d -depth -empty -print0 | xargs -0 rmdir


Ich habe übrigens an allen Stellen, die mit $file und $directory hantieren, gequotet. Beim ersten Pfad mit Leerzeichen weisst Du, warum ;)

Zur Übersicht hier nochmal meine Version bereinigt:



#!/bin/sh
# ins Verzeichnis wechseln
cd /data/public
# find-Orgie loslassen - zu klaeren ist noch ob atime / mtime und +/-tage
find . -type f -atime -420 | while read file; do
# Verzeichnisname
directory="`dirname \"$file\"`"
#Verzeichnis erstellen
mkdir -p "../müll/$directory"
# und datei reinmoven
mv "$file" "../müll/$directory/"
done
#leere Verzeichnisse wegputzen
find /data/public -mindepth 1 -type d -depth -empty -print0 | xargs -0 rmdir


Jan

jan61
11-05-2007, 23:55
Einen hab ich noch ;)

es geht auch in 1 Zeile (bzw. 2, wenn man das Bereinigen mitzählt):


find . -type f -mtime +10 -printf "mkdir -p \"../müll/%h\" && mv \"%p\" \"../müll/%h\"\n" | sh
find /data/public -mindepth 1 -type d -depth -empty -print0 | xargs -0 rmdir

Der "find" ist eben was Besonderes ;)
Was passiert da? find sucht alle Dateien, die zuletzt vor mehr als 10 Tagen geändert wurden. Die "printf"-Option schreibt jetzt für jede gefundene Datei eine Zeile der Form:

mkdir -p "../müll/Verzeichnis" && mv "Datei" "../müll/Verzeichnis"
und diese Zeile wird einer Shell als Kommando übergeben - die führt sie dann aus.

SCNR :)
Jan

Radis
12-05-2007, 09:46
Hi,

vielen Dank! Ich ärger mich da mit 'sed' rum und muss dann feststellen dass es 'dirname' gibt. Damit klappt's natürlich!

Stimmt, auch mit './' vorndran funktioniert ein 'mkdir ./oberverz/./neues_verz', damit kann ich mir das wegschneiden vom './' sparen.

Vor dem 'mkdir' will ich eine Überprüfung machen, um keine Mails vom crond zu erhalten, denn mkdir bringt ne Meldung wenn das Verzeichnis bereits existiert.
Aber besser ist vielleicht ein 'mkdir -p "../müll/$directory" 2>/dev/null'.

Was ich tatsächlich brauche sind alle Dateien die keiner mehr seit 420 Tagen genutzt hat, also ein 'find -atime +420'.

Der Rest des Scripts war eher rapid-prototyping im Kopf, aber deine Tipps helfen mir echt weiter, auch wenn ich brauchen werd bis ich's versteh; v.a. das printf ist doch sehr kryptisch da liegt mir die Version mit ein paar mehr Zeilen eher ;-)

Nochmals vielen Dank!

jan61
13-05-2007, 14:09
Moin,



...
Vor dem 'mkdir' will ich eine Überprüfung machen, um keine Mails vom crond zu erhalten, denn mkdir bringt ne Meldung wenn das Verzeichnis bereits existiert.
Aber besser ist vielleicht ein 'mkdir -p "../müll/$directory" 2>/dev/null'.
...


Die Überprüfung kannst Du kompakt so einbauen:

test -d "../müll/$directory" || mkdir -p "../müll/$directory"

Jan

403
14-05-2007, 00:57
Hallo,

ich wuerde in Zeile 1 noch etwas sowas miteinbauen, falls /data/public mal nicht lesbar
ist:


cd /data/public || echo "$0 failed to enter directory /data/public"; exit 1

Warum?

cd wuerde sonst nach /root wechseln und da will man den
find Befehl nicht ausfuehren.

Gruss 403

PS, Die eigene Fehlermeldung ist nur Kosmetic, da cd ja dann ein
Permission denied sagt.

Radis
16-05-2007, 11:34
Ich benutze jetzt absolute Verzeichnispfade, damit umgeh ich das unfreiwillige "cd /root" auch, außerdem kann man sie schön als Variablen am Anfang des Script setzen, damit bleibt das Script auch flexibler.

Vielen Dank für die Tipps!

jan61
20-05-2007, 20:06
...Der Rest des Scripts war eher rapid-prototyping im Kopf, aber deine Tipps helfen mir echt weiter, auch wenn ich brauchen werd bis ich's versteh; v.a. das printf ist doch sehr kryptisch da liegt mir die Version mit ein paar mehr Zeilen eher ;-)

Hat aber funktioniert %-/ - ich teste sowas immer, indem ich vor das Kommando ein echo setze (dann muss man natürlich die Quotes ändern), und bevor ich Dir das Ding geschickt habe, hab ich das echo wieder entfernt - und dann einmal zu oft <ENTER> gedrückt - schwupps war mein ~/tmp leer, wo ich doch die ganzen nützlichen "mal eben ausprobieren"-Programme hinpacke ;) Das Verzeichnis ist mittlerweile dicker als alle Projektverzeichnisse.

Jan