# [SHELL-SCRIPT] Die älteste Datei löschen

## Pegasus87

Hallo,

ich suche einen Shell-Script, der mir die älteste Datei aus einem Verzeichnis sucht und löscht, bevor eine neue angelegt wird.

Bsp.: Ich habe einen Script, der mir mit tar Backups von Verzeichnissen anlegt. Nun sollen immer die 5 letzten Backups gespeichert werden und bevor ein neues Backup angelegt wird (also das Script ausgeführt wird), das älteste Backup gelöscht werden.

Im Prinzip ganz einfach, aber wie kann man das umsetzen?

Hat jemand eine Idee? Oder noch eine Frage?

Danke für eure Hilfe!

----------

## SinoTech

Einfach den "-t" switch von ls benutzen, welcher die Ausgabe nach dem Alter der Dateien sortiert (von der jüngsten (oben) zu der ältesten (unten)), sowie den "-1" switch (eins). Der "-1" switch listet die Dateien untereinander auf (Ähnlich zu "-l" (klein L), welches aber noch zusätzlichen die Größpe, Besitzer etc. ausgibt).

```

$ ls -1t --color=none | tail -n 1 | xargs rm -rf

```

Mfg

Sino

----------

## STiGMaTa_ch

```
for a in `ls -1t`;do AeltesteDatei=$a;done

rm $AeltesteDatei
```

#Edit

SinoTech war schneller...  :Smile: 

Lieber Gruss

STiGMaTa

----------

## Pegasus87

 *SinoTech wrote:*   

> Einfach den "-t" switch von ls benutzen, welcher die Ausgabe nach dem Alter der Dateien sortiert (von der jüngsten (oben) zu der ältesten (unten)), sowie den "-1" switch (eins). Der "-1" switch listet die Dateien untereinander auf (Ähnlich zu "-l" (klein L), welches aber noch zusätzlichen die Größpe, Besitzer etc. ausgibt).
> 
> ```
> 
> $ ls -1t --color=none | tail -n 1 | xargs rm -rf
> ...

 

Vielen dank, das wars, was ich suchte   :Very Happy: 

----------

## smg

$ ls -1t -A --color=none | tail -n 1 | xargs rm -rf 

Würde ich noch vorschlagen, man beachte das -A.  :Wink: 

Bye.

----------

## SinoTech

Nice, "-A" habe ich noch nicht gekannt .. naja, man kann schließlich auch nicht jeden switch kennen  :Smile: .

Mfg

Sino

----------

## Pegasus87

Noch eine Frage:

Wenn ich das jetzt mit 

```
 ls -1t -A --color=none | tail -n 1 | xargs rm -rf 
```

 mache, funktioniert das ja schon ganz gut, aber es wird immer die älteste Datei gelöscht, egal wieviele im Verzeichnis sind.

Wie müsste eine Schleife aussehen, die zunächst überprüft, ob z.B. mindestens 3 Dateien vorhanden sind und nur dann löscht?

----------

## smg

Was für einen Sinn würde das machen?

Aber okay: 

```
[ $(ls -A | wc -l) -ge 3 ] && ls -1t -A --color=none | tail -n 1 | xargs rm -rf

```

Bye.

----------

## Pegasus87

 *hagbard_ wrote:*   

> Was für einen Sinn würde das machen?
> 
> Aber okay: 
> 
> ```
> ...

 

Danke, funktioniert!

Sinn ist folgender:

Es sollen in dem Verzeichnis immer die letzten 3 Backups einer Datei vorhanden sein.

Wenn nun ein User eine Backupdatei gelöscht hat und somit nur noch 2 da sind, soll natürlich eine dritte Datei erstellt werden und nich eine gelöscht und eine erstellt werden, so dass man wieder bei 2 Dateien wäre. Deshalb die Überprüfung.

----------

## monade

 *hagbard_ wrote:*   

> 
> 
> ```
> [ $(ls -A | wc -l) -ge 3 ] && ls -1t -A --color=none | tail -n 1 | xargs rm -rf
> ```
> ...

 

Nur aus Interesse: für was ist die die --color-Angabe notwendig?

monade

----------

## smg

Des woiss i au nit, oba mei Vorgänger ham des so vorgeschloge.  :Wink: 

Bye.

----------

## Pegasus87

 *monade wrote:*   

>  *hagbard_ wrote:*   
> 
> ```
> [ $(ls -A | wc -l) -ge 3 ] && ls -1t -A --color=none | tail -n 1 | xargs rm -rf
> ```
> ...

 

Damit kannste die Ausgabe einfärben, damits hübscher aussieht:

MAN-Page:

--color[=WANN]

              Kontrolle  wann  Farbe  zum  unterscheiden der Datei- typen eingesetzt wird. WANN kann never, always oder auto

              sein.

----------

## Anarcho

 *hagbard_ wrote:*   

> Was für einen Sinn würde das machen?
> 
> Aber okay: 
> 
> ```
> ...

 

Wenn du immer wieder auf 3 zurück willst, egal wieviele Dateien drin sind:

```
while [ $(ls -A | wc -l) -ge 3 ]; do ls -1tA --color=none | tail -n 1 | xargs rm -rf; done
```

----------

## Earthwings

Sollte noch erwähnt werden, dass Verzeichnisse und Dateien mit Sonderzeichen (Leerzeichen etc.) Probleme machen werden.

@Anarcho: Das wird aber ne Endlosschleife, wenn drei Verzeichnisse in dem Ordner sind oder das Löschen aus anderem Grund fehlschlägt, oder arg langsam, falls eine sehr große Zahl Dateien vorhanden ist...

----------

## Anarcho

 *Earthwings wrote:*   

> Sollte noch erwähnt werden, dass Verzeichnisse und Dateien mit Sonderzeichen (Leerzeichen etc.) Probleme machen werden.
> 
> @Anarcho: Das wird aber ne Endlosschleife, wenn drei Verzeichnisse in dem Ordner sind oder das Löschen aus anderem Grund fehlschlägt, oder arg langsam, falls eine sehr große Zahl Dateien vorhanden ist...

 

Also den Fall mit den 3 Verzeichnissen kann ich nicht nachvollziehen:

```
workstation test $ ll

insgesamt 0

workstation test $ mkdir ordner1

workstation test $ mkdir ordner2

workstation test $ mkdir ordner3

workstation test $ ll

insgesamt 12K

drwxr-xr-x  2 maz network 4,0K  2. Jan 16:01 ordner1

drwxr-xr-x  2 maz network 4,0K  2. Jan 16:01 ordner2

drwxr-xr-x  2 maz network 4,0K  2. Jan 16:01 ordner3

workstation test $ while [ $(ls -A | wc -l) -ge 3 ]; do ls -1tA --color=none | tail -n 1 | xargs rm -rf; done

workstation test $ ll

insgesamt 8,0K

drwxr-xr-x  2 maz network 4,0K  2. Jan 16:01 ordner2

drwxr-xr-x  2 maz network 4,0K  2. Jan 16:01 ordner3

workstation test $
```

Das mit dem Fehlschlagen des Löschens kann in der Tat passieren, aber das kann man dann durch eine kleine Änderung beheben:

```
 FTEST=""; while [ $(ls -A | wc -l) -ge 3 -a "$FTEST" == "" ]; do ls -1tA --color=none | tail -n 1 | xargs rm -rf 2>/dev/null || FTEST="y"; done
```

----------

## Earthwings

Ja, hast recht, rm -rf macht ja auch Ordner platt. Womit ein neues Problem entsteht: Wenn eine Datei names "/ foo" im Ordner existiert, wird dank fehlenden Quotes der Inhalt der gesamten Festplatte gelöscht. IMHO sollte man rm -rf *nie* in einem Skript benutzen.

----------

## Anarcho

 *Earthwings wrote:*   

> Ja, hast recht, rm -rf macht ja auch Ordner platt. Womit ein neues Problem entsteht: Wenn eine Datei names "/ foo" im Ordner existiert, wird dank fehlenden Quotes der Inhalt der gesamten Festplatte gelöscht. IMHO sollte man rm -rf *nie* in einem Skript benutzen.

 

Ist ja gut. Das -rf kommt nicht von mir, ich habe nur die while-schleife drum gesetzt. Aber wenn du es ganz genau haben willst:

```
#!/usr/bin/perl

$count = 0;

$ls=`ls -1tA`;

@files = split("\n",$ls);

$max = @files;

print "No. of Files: ".$max."\n";

for ($i=0;$i<$max;$i++) {

        $count++;

        if ($count >= 3) {

                print "DEL: ".$files[$i]."\n";

                system(sprintf("rm -rf '%s'",$files[$i]));

        } else {

                print $files[$i]."\n";

        }

}
```

Dann machen wir eben ein Perl-Script draus! Dann ist zwar immer noch das -rf drin, aber zumindest sind jetzt leerzeichen egal. Wenn man weiss das nur dateien als Backup da sind, dann sollte man das rf löschen (und vielleicht noch die Verzeichnisse rausfiltern).

----------

## smg

Oha, das ist aber kein Shellscript mehr oder? Sondern Perl. *g*

Kann ja jemand nach SH/Bash portieren, bin grad zu faul. 

Bye.

----------

## Deever

Oje, bitte verzeiht, daß ich an dieser Stelle nicht viel früher eingeschritten bin! Schade um die vielen, unnötigen Tastenanschläge!

Folgendes Kommando löst Pegasus87's Problem:

```
$ rm /ver/zeich/nis/*(.Om[1])
```

Dies setzt natürlich voraus, daß man die Z-Shell benutzt, was aber auch zu empfehlen ist. Die Bash mag zum Starten von Progammen und der Notwendigkeit, möglichst lange "Röhrensysteme" zu verlegen, geeignet sein; vernünftig arbeiten läßt sich mit anderem jedoch besser.

Gruß,

/dev

----------

## Anarcho

 *Deever wrote:*   

> Oje, bitte verzeiht, daß ich an dieser Stelle nicht viel früher eingeschritten bin! Schade um die vielen, unnötigen Tastenanschläge!
> 
> Folgendes Kommando löst Pegasus87's Problem:
> 
> ```
> ...

 

Wir werden hier doch alle nach Tastenanschlägen bzw. Zeilen bezahlt!   :Twisted Evil: 

----------

## smg

 *Deever wrote:*   

> Oje, bitte verzeiht, daß ich an dieser Stelle nicht viel früher eingeschritten bin! Schade um die vielen, unnötigen Tastenanschläge!
> 
> Folgendes Kommando löst Pegasus87's Problem:
> 
> ```
> ...

 

Unnötig sind sie nicht, wenn der OP nämlich die Bash benutzt.

Bye.

----------

