Note: yay cache .git root cause, find -prune/-delete gotcha, paccache timer
This commit is contained in:
@@ -324,6 +324,115 @@ find . -type f -name "*.tmp" -delete
|
||||
find . -name "*.tmp" -delete
|
||||
```
|
||||
|
||||
### -delete und -prune sind unvereinbar (wichtig!)
|
||||
|
||||
**`-delete` aktiviert automatisch `-depth`.** Bei `-depth` (Tiefensuche) ist `-prune`
|
||||
aber wirkungslos – der Schutz wird also genau dann aufgehoben, wenn man ihn braucht.
|
||||
|
||||
```bash
|
||||
# FALSCH: -prune schützt NICHT, find warnt und führt den Befehl trotzdem aus!
|
||||
find ~/.cache -name .git -prune -o -type f -atime +30 -delete
|
||||
```
|
||||
|
||||
Ausgabe von GNU find:
|
||||
|
||||
```
|
||||
find: Die Option -delete aktiviert -depth automatisch, aber -prune ist wirkungslos,
|
||||
wenn -depth aktiv ist. In diesem Fall muss -depth zusätzlich angegeben werden.
|
||||
```
|
||||
|
||||
Das ist eine **Warnung, kein Fehler** – der Befehl läuft weiter, mit deaktiviertem Schutz.
|
||||
Das hat im April 2026 bei einem AUR-Cache-Cleanup die `.git/HEAD`- und `.git/config`-Dateien
|
||||
von 24 Paketen gelöscht (siehe [[IT-Know-How/Linux/yay Cache reparieren]]).
|
||||
|
||||
**Lösung: `-prune` durch `-not -path` ersetzen.** `-path` funktioniert auch bei `-depth`:
|
||||
|
||||
```bash
|
||||
# RICHTIG: -not -path statt -prune
|
||||
find ~/.cache -type f -atime +30 -not -path '*/.git/*' -delete
|
||||
```
|
||||
|
||||
Verifiziertes Verhalten:
|
||||
|
||||
| Datei | Ergebnis |
|
||||
|-------|----------|
|
||||
| `normal/old.txt` (alt) | gelöscht |
|
||||
| `.git/HEAD` (alt) | **bleibt erhalten** |
|
||||
| `.git/config` (alt) | **bleibt erhalten** |
|
||||
|
||||
> **Merksatz:** `-prune` funktioniert nur bei der *Breitensuche* (Voreinstellung).
|
||||
> Sobald `-depth` im Spiel ist – etwa durch `-delete` oder `-exec` mit `{} +` –
|
||||
> muss der Ausschluss über `-not -path` oder `-not -name` erfolgen.
|
||||
|
||||
### Ausschlusslisten sicher formulieren
|
||||
|
||||
Mehrere Ausschlüsse kombinieren:
|
||||
|
||||
```bash
|
||||
# .git und node_modules ausschließen
|
||||
find . -type f -atime +30 -not -path '*/.git/*' -not -path '*/node_modules/*' -delete
|
||||
|
||||
# statt .git prüfen: nur in echten Cache-Verzeichnissen löschen
|
||||
find ~/.cache -mindepth 2 -type f -atime +30 -not -path '*/.git/*' -delete
|
||||
```
|
||||
|
||||
Immer vorher mit `-print` prüfen, wie viele Dateien betroffen sind:
|
||||
|
||||
```bash
|
||||
find ~/.cache -type f -atime +30 -not -path '*/.git/*' -print | wc -l
|
||||
```
|
||||
|
||||
### noatime: warum -atime auf dem Root-Filesystem täuscht
|
||||
|
||||
Bei einem `noatime`-Mount wird die Zugriffszeit beim **Lesen nicht mehr aktualisiert**.
|
||||
`-atime` misst dann faktisch nur noch das Alter der letzten **Schreiboperation** –
|
||||
also praktisch `mtime`:
|
||||
|
||||
```bash
|
||||
# Mount-Optionen prüfen
|
||||
findmnt -T /home
|
||||
# TARGET SOURCE FSTYPE OPTIONS
|
||||
# / /dev/... ext4 rw,noatime,commit=60
|
||||
|
||||
# Bei noatime ist -atime +30 == "in 30 Tagen nicht mehr geschrieben"
|
||||
```
|
||||
|
||||
Folge: Ein `find -atime +30 -delete` löscht auch Dateien, die **täglich gelesen** werden –
|
||||
sofern sie 30 Tage lang nicht geschrieben wurden. Bei Cache-Bereinigungen ist `-mtime`
|
||||
meist die ehrlichere Wahl, weil Caches ohnehin nur geschrieben, nie gelesen werden.
|
||||
|
||||
`atime` vs. `mtime` im Vergleich:
|
||||
|
||||
| Mount | `-atime +30` bedeutet |
|
||||
|-------|----------------------|
|
||||
| `relatime` (Standard) | wirklich: seit 30 Tagen nicht mehr gelesen |
|
||||
| `noatime` | seit 30 Tagen nicht mehr **geschrieben** |
|
||||
| `strictatime` | wie `relatime`, aber exakter Zeitstempel |
|
||||
|
||||
### Sicheres Aufräumen mit Ausschlussliste
|
||||
|
||||
Kombiniertes Rezept für Cache-Bereinigungen – zuerst prüfen, dann löschen:
|
||||
|
||||
```bash
|
||||
# 1. Was würde gelöscht? (Anzahl + Größe)
|
||||
find ~/.cache -type f -atime +30 -not -path '*/.git/*' -print | wc -l
|
||||
find ~/.cache -type f -atime +30 -not -path '*/.git/*' -printf '%s\n' \
|
||||
| awk '{s+=$1} END {printf "%.2f GB\n", s/1024/1024/1024}'
|
||||
|
||||
# 2. Abhängig vom Ziel:
|
||||
# a) altersbasiert: .git über -not -path ausnehmen
|
||||
find ~/.cache -type f -atime +30 -not -path '*/.git/*' -delete
|
||||
|
||||
# b) nur bestimmte Artefakte: die Endungen begrenzen, .git bleibt außen vor
|
||||
find ~/.cache -type f \( -name '*.pkg.tar.zst' -o -name '*.AppImage' \
|
||||
-o -name '*.tar.gz' \) -not -path '*/.git/*' -delete
|
||||
```
|
||||
|
||||
> **Nicht mit `-prune` löschen:** `-delete` schaltet intern auf `-depth` um, und
|
||||
> `-prune` wird dann wirkungslos. Wer trotzdem `-prune` im selben Befehl nutzt,
|
||||
> verliert den `.git`-Schutz exakt im Moment des Löschens. Ausschlüsse immer über
|
||||
> `-not -path` formulieren.
|
||||
|
||||
### Zu viele Argumente
|
||||
|
||||
```bash
|
||||
@@ -360,3 +469,4 @@ fd -e jpg -x convert {} ... # Mit exec
|
||||
- [[IT-Know-How/Linux/BASH Basics/rsync]] - Dateien synchronisieren
|
||||
- [[IT-Know-How/Linux/BASH Basics/sed]] - Gefundene Dateien bearbeiten
|
||||
- [[IT-Know-How/Linux/BASH Basics/awk]] - Ausgabe von find verarbeiten
|
||||
- [[IT-Know-How/Linux/yay Cache reparieren]] - Realer Anwendungsfall: Cache-Cleanup hat `.git` zerstört
|
||||
|
||||
Reference in New Issue
Block a user