PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Suche Linux Befehl um alles außer bestimmten Dateien/Ordnern zu löschen


Käsetoast
2013-10-24, 10:30:18
Hi!

Ich bräuchte eure Hilfe, da ich mir gerne eine .sh Datei schreiben möchte, die einen Löschvorgang automatisiert. Ich habe ein Projektverzeichnis mit drei Ordnern. Ich führe derzeit Simulationen durch, die dafür sorgen, dass da dann Ordner hinzukommen, die die Zeit als Namen haben, also z.B. "1", "1.5", "2" und so weiter. Aus einem Grund, den ich noch nicht verstehe, ist ein Überschreiben der bisherigen Zeitschritte momentan aber nicht möglich, d.h. man muss die ganzen Zeitschrittordner rauslöschen. Da das eine recht nervige Arbeit ist, wollte ich den Vorgang automatisieren. Da ich aber von den Linux Shell Kommandos nur sehr wenig Ahnung habe wollte ich fragen, wie so ein Befehl auszusehen hat, damit ich mir den dann in eine .sh Datei setzen kann, die sich bequem ausführen lässt?

Also nochmal in Kurzform:
Alles in einem Ordner löschen außer drei Ordnern mit speziellem Namen (sowie zusätzlich dann der .sh Datei wo das Kommando drinsteht natürlich)...

#44
2013-10-24, 10:41:39
Wenn du den zu löschenden Ordnern ein Prefix geben kannst:

Beispiel mit Prefix "simschritt_" im homeverzeichnis
rm -rf /home/kaesetoast/projektverzeichnis/simschritt_*

Denkbar wäre auch sowas

mv /home/kaesetoast/projektverzeichnis/nichtzuloeschenderordner1 /tmp
mv /home/kaesetoast/projektverzeichnis/nichtzuloeschenderordner2 /tmp
mv /home/kaesetoast/projektverzeichnis/nichtzuloeschenderordner3 /tmp
rm -rf /home/kaesetoast/projektverzeichnis/*
mv /tmp/nichtzuloeschenderordner1 /home/kaesetoast/projektverzeichnis/
mv /tmp/nichtzuloeschenderordner2 /home/kaesetoast/projektverzeichnis/
mv /tmp/nichtzuloeschenderordner3 /home/kaesetoast/projektverzeichnis/

So hinbiegen, dass es für deinen Fall funktioniert musst du es natürlich selbst.

Käsetoast
2013-10-24, 11:13:56
Hmm - ok also mit Verschieben. Wird da denn auch physisch was verschoben, oder wird nur der "Eintrag" für die Position der Datei geändert? Hatte da nämlich auch dran gedacht, aber war mir nicht sicher, ob der dann nicht anfängt die Dateien rumzukopieren und das wäre bei größeren Ordnern ja blöd...

#44
2013-10-24, 11:20:37
Hmm - ok also mit Verschieben. Wird da denn auch physisch was verschoben, oder wird nur der "Eintrag" für die Position der Datei geändert? Hatte da nämlich auch dran gedacht, aber war mir nicht sicher, ob der dann nicht anfängt die Dateien rumzukopieren und das wäre bei größeren Ordnern ja blöd...
Sofern die Ordner auf der selben Partition liegen, werden die Daten selbst nicht verschoben - nur der Zuordnungseintrag.

Es gibt wohl auch noch eine andere Möglichkeit: find
Habe ich auf superuser.com gefunden und nicht wirklich selbst ne Ahnung...

find /home/kaesetoast/projektordner ! -name nichtzloeschenderordner1 ! -name nichtzloeschenderordner2 ! -name nichtzloeschenderordner3 -maxdepth 1 -delete

Vorher ggf. testen mit:
find /home/kaesetoast/projektordner ! -name nichtzloeschenderordner1 ! -name nichtzloeschenderordner2 ! -name nichtzloeschenderordner3 -maxdepth 1 -print

Avalox
2013-10-24, 11:28:03
Hmm - ok also mit Verschieben. Wird da denn auch physisch was verschoben, oder wird nur der "Eintrag" für die Position der Datei geändert? Hatte da nämlich auch dran gedacht, aber war mir nicht sicher, ob der dann nicht anfängt die Dateien rumzukopieren und das wäre bei größeren Ordnern ja blöd...

Move schaufelt Daten wenn sich das Ziel auf einer anderen Partition, oder Datenträger befindet.

Zur Frage hätte ich jetzt eher an ein

rm -rf `ls /{Ziel} | grep -v {Ausnahme}` oder sowas gedacht.

PHuV
2013-10-24, 11:38:27
Frag doch den Chef :cool:

Getestet und läuft!

#!/bin/bash
# Generiere Löschscript
# Usage
# gen_loeschscript.sh Verzeichnis Name des Scriptes
# Made by PHuV für Käsetoast im 3D-Center
# Version 1.0, 24.10.2013
# Initiale Version

# Dein Verzeichnisstamm, z.B. /home/Name/data
# Einmal fest
#STAMVERZ="DeinVerzeichnisstamm"
# einmal variabel über Kommandozeile
STAMVERZ=$1
# Löschscript
#LOESCHSC="/home/Name/scripte/loesche_verzeichnisse.sh"
LOESCHSC=$2

DATE=`date +%d.%m.%Y`
TIME=`date +%H:%M:%S`

# Wenn Du das nicht per Parameter so übergeben magst, if-Block wegkommentieren
if [ $# -lt 2 ];then
echo "Usage: `basename $0` Verzeichnis Script_Name"
echo "z.B. $0 /home/user/data /tmp/loeschscript.sh"
echo "In Windows mit cywintools"
echo "z.B. $0 \"/home/user/data\" \"/tmp/loeschscript.sh\""
exit 0
else
shift 2
fi


# Lege das Script initial an, ein eventuell vorhandenes wird überschrieben
echo "# Mein Loeschscript" >${LOESCHSC}
echo "# Erzeugt am $DATE um $TIME" >>${LOESCHSC}
echo >>${LOESCHSC}

# Gehe in das Stammverzeichnis
cd ${STAMVERZ}

# Lese mal das Verzeichnis aus
for verzeichnis in `ls`
do
case ${verzeichnis} in
# nix löschen
Magichnichtloeschen1) continue;;
Magichnichtloeschen2) continue;;
Magichnichtloeschen3) continue;;
# Rest löschen
# Wenn Du keine Meldungen magst, ein >/dev/null dazuhängen"
*) echo "rm -rf ${verzeichnis}" >> ${LOESCHSC}
esac
done

echo "Das Loeschscript unter ${LOESCHSC} sieht nun so aus"
echo "----------------"
cat ${LOESCHSC}
echo "----------------"

exit 0

#44
2013-10-24, 11:43:11
Das wird nur klappen, wenn die Simulationsschritte immer gleich und bei der Scriptgenerierung alle vorhanden sind.

Ansonsten: Was ein Overkill :ugly:
Ganz davon abgesehen, das jemandem vorzusetzen, der von Shellscripting kaum bis keine Ahnung hat...

Trozdem: :uup:

PHuV
2013-10-24, 12:00:08
Du bringst mich noch auf eine Idee, man könnte die nicht gewollten Verzeichnisse noch mit dazu in den Argumentenaufruf mit reinbringen, aber dann wird es mit dem Case etwas schwierig, und man müßte es anders realisieren, sprich zuerst ein Liste erzeugen, und dann alle nicht gewollten Verzeichnisse rauslöschen:

echo `ls ${STAMVERZ}` >> liste_verzeichnisse1

grep -v "Magichnicht1|Magichnicht2|Magichnicht" liste_verzeichnisse1 >>liste_verzeichnisse2

while read verzeichnisse
do
echo "rm -rf ${verzeichnisse}" >>loesch_script.sh
done <liste_verzeichnisse2

exit 0

Der Vorteil über erzeugte Dateien ist der, daß man sie loggen bzw. das Ergebnis betrachten kann.

Käsetoast
2013-10-24, 13:30:15
Auf jeden Fall schonmal Danke für eure Hilfen. Echt klasse hier Leute mit Ahnung zu haben... (y)

Gast
2013-10-24, 13:35:50
rm -rf !(blah1,blub2,blahblubb3)

wrdaniel
2013-10-24, 13:38:06
Hätte jetzt nur für die Verzeichnisse dies genommen.

rm [0-9]* -r

PHuV
2013-10-24, 16:49:43
rm -rf !(blah1,blub2,blahblubb3)
Das funktioniert schon mal nicht, mit Cygwin und mit Linux getestet, es geht nur mit einem Argument:
rm -rf !(blah1)

Gast
2013-10-24, 17:51:47
ja, weil ich hirschkuh "," mit "|" vertauscht hab. :/

rm -rf !(blah1|blub2|blahblubb3)

sry dafür :D

PHuV
2013-10-24, 18:31:45
Geilomat, klasse Lösung :up:

Wußte gar nicht, daß es so auch geht. "Again what learned", wie der Loddar so sagt. Danke. Man lernt bei Shell wirklich nicht aus, egal wie lange man das macht.

vanquish
2013-10-24, 19:10:18
So ... Accountdaten wieder gefunden. Dieses Captcha-Gedöns am Notebook ist echt das Letzte! Wer sich das wieder ausgedacht hat.

Gerne, jederzeit wieder! ;)

Es wäre auch noch möglich in der in der Shell passende Variablen festzulegen:

export GLOBIGNORE=blah1:blah2:blahblubb3
rm -rf *

Das Zurücksetzen aber nicht vergessen. ;)

Lokadamus
2013-10-24, 19:11:53
Geilomat, klasse Lösung :up:

Wußte gar nicht, daß es so auch geht. "Again what learned", wie der Loddar so sagt. Danke. Man lernt bei Shell wirklich nicht aus, egal wie lange man das macht.Lies mal durch und sag mir, ob man damit was lernen kann. Ich hab entweder keine Lust oder keine Zeit zum Lesen. :(

http://www.tldp.org/LDP/Bash-Beginners-Guide/html/
http://www.tldp.org/LDP/abs/html/

#44
2013-10-24, 19:20:44
Lies mal durch und sag mir, ob man damit was lernen kann. Ich hab entweder keine Lust oder keine Zeit zum Lesen. :(
Na mit der Einstellung wird es sowieso nix :tongue:

Das ist glaube ich das Dokument, bei dem ich am häufigsten Ende, wenn ich nach Hilfestellung rund um Bash/Bash-Scripting google.
Ich fand's bisher immer gut.

PHuV
2013-10-24, 21:15:54
Lies mal durch und sag mir, ob man damit was lernen kann. Ich hab entweder keine Lust oder keine Zeit zum Lesen. :(

Hm, am besten lernt man, in dem man konkrete Probleme hat und dann versucht, sie zu lösen. Deine Links bieten nur eine Basis. Letztlich muß man meinstens auch noch die man-Pages der jeweiligen Plattformen lesen (AIX, Solaris, HP-UX, Linux etc.), weil sich diese doch in manchen Befehlen unterscheiden. Dazu noch die diversen Shell-Varianten (sh, ksh, bash, zsh..), die diverse Dinge bieten, was aber dann auch bedeuten kann, daß sie nicht überall gleich funktionieren. Im Endeffekt schaut man dann nach, wie man diverse Dinge lösen kann, z.B. String-Operationen, und dann einfach mal probieren und tun. Der Rest ergibt sich dann aus der Praxis. Wie ich oben sagte, ich lerne jedes Mal immer wieder was neues dazu. Bei Shell-Scripten kann man zwar viel machen, aber auch vieles falsch oder ineffizient. Und das wird sogar oft in diversen Büchern und Anleitungen so empfohlen:

Beispiel:
#Schlecht, da sehr langsam
$zaehler= `expr $zaehler+ 1`

Findet man haufenweise so. Ist aber ganz schlecht, wenn man viele Zeilen oder größe Dateien verarbeiten muß. Für jeden expr-Aufruf wird ein neuer Prozess bzw. fork generiert, was dann die Laufzeit erheblich verlängert. Viel besser ist
#Viel schneller
$zaehler=$(($zaehler+1))

Kann ja jeder selbst prüfen:

#!/bin/sh

i=1
ende=1000

while [ $i -le $ende ]
do
echo $i
#Variante langsam
i=`expr $i + 1`
# Variante schnell
#i=$((i + 1))
done
Einfach mal die eine ausprobieren, und dann durch die andere kommentiere austauschen.

sei laut
2013-10-24, 23:23:37
PHuV liegt richtig, du lernst nichts durch lesen, sondern durch konkrete Problemlösungen.
Ich habe z.B. ein Problem, dass ich vor Strings ein -n machen muss.
Meine Zeile sieht also so aus:
hallo1 hallo2 hallo3
Ich brauche:
-n hallo1 -n hallo2 -n hallo3
Die Strings sind zufällig, können beliebig heißen.

hallos="hallo1 hallo2 hallo3"
for i in $hallos; do
# geht nicht:
$alle=`echo "-n $i"`
# geht, überschreibt aber meine Einträge:
alle=`echo "-n $i"`
# meine Lösung:
echo "-n $i" >> temp-datei
done

Nur mal als Beispiel und vielleicht kennt ja jemand hier sogar einen schöneren Weg. Beim oberen kommt "Kommando nicht gefunden :-n"
Nur da das ursprüngliche Thema schon sauber gelöst ist. :D

PHuV
2013-10-25, 10:26:18
hallos="hallo1 hallo2 hallo3"
for i in $hallos; do
# geht nicht:
$alle=`echo "-n $i"`
# geht, überschreibt aber meine Einträge:
alle=`echo "-n $i"`
# meine Lösung:
echo "-n $i" >> temp-datei
done

Es ist doch klar, warum es hier Deine Werte überschreibt. ;) Du mußt beim Programmieren Dir den bisherigen Wert merken oder dazu ergänzen:
alle=`echo "-n $i ${alle}"`
Übrigens solltest Du bei Leerzeichen in Variablen lieber ${var} und "${var}" verwenden. Sonst kann es sein, daß durch den Default IFS (internal field separator), der immer auf " " Leerzeichen bzw. Blank lautet, nur das erste Wort angezeigt wird. ;)

sei laut
2013-10-25, 12:17:21
Ich bin diese Schreibweise nicht gewohnt, da ich sonst meine Variablen immer auf billige Art erweitere. Aber ja, hab das nun auch heute morgen entdeckt und umgesetzt.
Trotzdem danke. :D

Allerdings sieht meine Lösung nun so aus: (auf die Idee, dass echo zuviel ist, kam ich aber auch nicht gleich)
blubb="${blubb} -n $i"
Bin mir bewusst, dass es nicht sauber ist ohne {}, aber unter bash ist mir da noch nichts passiert.

Lokadamus
2013-10-25, 17:29:58
Deine Links bieten nur eine Basis. Letztlich muß man meinstens auch noch die man-Pages der jeweiligen Plattformen lesen (AIX, Solaris, HP-UX, Linux etc.), weil sich diese doch in manchen Befehlen unterscheiden. Dazu noch die diversen Shell-Varianten (sh, ksh, bash, zsh..), die diverse Dinge bieten, was aber dann auch bedeuten kann, daß sie nicht überall gleich funktionieren. Im Endeffekt schaut man dann nach, wie man diverse Dinge lösen kann, z.B. String-Operationen, und dann einfach mal probieren und tun. Der Rest ergibt sich dann aus der Praxis. Die Probleme kenne ich schon alle, alleine weil ich FreeBSD benutze. ;)
Da ist tcsh die Standardshell und nicht bash, dazu kommt, dass einige Befehle sich mit der Zeit ändern und man die Sachen noch einmal durchschauen sollte.
DTrace, ZFS und noch ein paar andere Sachen würde ich gerne mal näher anschauen, aber wann? Irgendwo will ich auch noch sowas wie ein Leben haben.

Momentan sind meine Skripte auch eher Anfängerkram und sie machen nur Kleinigkeiten, aber sie erfüllen ihren Zweck.

Achja, wenn die Dateien älter sind als eine Stunde oder so kann man noch mit der Uhrzeit rumspielen bzw. es versuchen.
http://www.cosni.de/fragen/4ee1e9e486cbf/linux-dateien-aelter-als-x-in-einem-verzeichnis-loeschen

littlejam
2013-11-18, 20:58:02
PHuV liegt richtig, du lernst nichts durch lesen, sondern durch konkrete Problemlösungen.
Ich habe z.B. ein Problem, dass ich vor Strings ein -n machen muss.
Meine Zeile sieht also so aus:
hallo1 hallo2 hallo3
Ich brauche:
-n hallo1 -n hallo2 -n hallo3
Die Strings sind zufällig, können beliebig heißen.


#!/bin/bash
hallos="hallo1 hallo2 hallo3"
echo ${hallos// / -n }
Zwar spät, aber probiers mal damit.

Gruß

PHuV
2013-11-18, 23:18:34
#!/bin/bash
hallos="hallo1 hallo2 hallo3"
echo ${hallos// / -n }
Zwar spät, aber probiers mal damit.

Gruß
Da hast ein Problem, weil Du die erste Variable damit nicht erwischt!

littlejam
2013-11-19, 20:22:01
Da hast ein Problem, weil Du die erste Variable damit nicht erwischt!
Jajaja...

#!/bin/bash
hallos="hallo1 hallo2 hallo3"
echo "-n "${hallos// / -n }

Immerhin ohne Schleife :D
Leider ist das {}-Zeug nicht vollständig RegExp-fähig, dann wäre das noch einfacher.
sed oder awk wäre auch dafür geeignet und sind für sowas imho auch gängiger.

Gruß

PHuV
2013-11-19, 22:02:14
sed oder awk wäre auch dafür geeignet und sind für sowas imho auch gängiger.
Uuuhh, ganz viele forks, nix gut. ;)

Ne, die Inline-Versionen sind immer vorzuzuiehen, besonders wenn viele oder große Dateien verarbeitet werden müssen.

littlejam
2013-11-20, 21:23:43
Uuuhh, ganz viele forks, nix gut. ;)

Ne, die Inline-Versionen sind immer vorzuzuiehen, besonders wenn viele oder große Dateien verarbeitet werden müssen.
Da widerspreche ich aber energisch :wink:

Fork ja, aber das ist in diesem Beispiel ein Einziges, die erste Idee mit der Schleife ist warscheinlich die Schlechteste/Unperformanteste.

Gerade für viele und große Dateien ist sed (aka streameditor) quasi erfunden worden. Glaub nicht, dass man ein 1GB Textfile in eine Variable laden kann um dann per Substitution o.Ä. Dinge zu ändern; ganz zu schweigen von der Performance.

Die {}-Geschichten sind aber fantastisch zum Skriptebauen, viele Schleifen, ifs etc. kann man sich dadurch sparen. Allein schon um die übergebenen Parameter auszuwerten und auf Syntax zu checken oder zur Fehlerbehandlung ist das schon Gold wert.

Gruß

sei laut
2013-11-21, 11:27:03
Gibts dazu eine Manpage oder eine Dokumentation? (ich nehme mal an, ja - weiß aber nicht, wonach ich suchen soll)
Wusste gar nicht, dass ${} diese Zusatzfunktionen hat.

PHuV
2013-11-21, 13:07:28
Das sind alles Inline-Funktionen der jeweiligen Shells, hier mußt Du bei deren man pages nachschlagen, und es vor allen Dingen erst mal ausprobieren. Vieles aus der ksh wurde in die bash übernommen und umgekehrt, aber das hängt dann von der Plattform und der dort installierten Version ab.

littlejam
2013-11-21, 18:40:16
Gibts dazu eine Manpage oder eine Dokumentation? (ich nehme mal an, ja - weiß aber nicht, wonach ich suchen soll)
Wusste gar nicht, dass ${} diese Zusatzfunktionen hat.
http://tldp.org/LDP/abs/html/parameter-substitution.html
Sehr gute Seite mit ausführlichen Beispielen.

Gruß