diff --git a/Linux/BASH Basics/BASH Basics.md b/Linux/BASH Basics/BASH Basics.md index c653252..1f711be 100644 --- a/Linux/BASH Basics/BASH Basics.md +++ b/Linux/BASH Basics/BASH Basics.md @@ -16,6 +16,7 @@ Sammlung wichtiger BASH-Befehle und Konzepte für die Linux-Konsole. ## Dateiverwaltung - [[IT-Know-How/Linux/BASH Basics/ls]] - Dateien auflisten und Größen anzeigen +- [[IT-Know-How/Linux/BASH Basics/fd]] - Dateien schnell suchen und gesammelt verarbeiten - [[IT-Know-How/Linux/BASH Basics/find]] - Dateien suchen, filtern und verarbeiten (inkl. Datum, Löschen) - [[IT-Know-How/Linux/BASH Basics/Symlinks]] - Symbolische Links erstellen und verwalten diff --git a/Linux/BASH Basics/fd.md b/Linux/BASH Basics/fd.md new file mode 100644 index 0000000..13ca827 --- /dev/null +++ b/Linux/BASH Basics/fd.md @@ -0,0 +1,392 @@ +# fd - Dateien und Verzeichnisse schnell suchen + +`fd` ist ein moderner, benutzerfreundlicher Ersatz für `find`. Die Standards +sind für die meisten interaktiven Suchen praktischer: Die Suche ist rekursiv, +Groß-/Kleinschreibung wird automatisch berücksichtigt, versteckte Dateien und +von Git ignorierte Dateien werden standardmäßig ausgelassen und die Ausgabe ist +farbig formatiert. + +`fd` ist kein vollständiger Ersatz für jede komplexe `find`-Abfrage. Für +interaktive Dateisuche ist es aber oft kürzer und übersichtlicher. + +## Installation + +Debian/Ubuntu: + +```bash +sudo apt update +sudo apt install fd-find +``` + +Bei Debian und Ubuntu heißt das Programm je nach Distribution `fdfind` statt +`fd`: + +```bash +fdfind --version +alias fd=fdfind # nur für die aktuelle Shell +``` + +Arch Linux: + +```bash +sudo pacman -S fd +``` + +Fedora: + +```bash +sudo dnf install fd-find +``` + +openSUSE: + +```bash +sudo zypper install fd +``` + +Installation prüfen: + +```bash +fd --version +fd --help +``` + +## Grundsyntax + +```bash +fd [OPTIONEN] [MUSTER] [SUCHPFAD...] +``` + +Ohne Argumente zeigt `fd` die Dateien und Verzeichnisse unterhalb des +aktuellen Verzeichnisses: + +```bash +fd +fd README.md # nach README.md suchen +fd README ~/Projekte # in ~/Projekte suchen +fd 'backup.*' /var/tmp # Suchmuster angeben +``` + +Das Muster wird standardmäßig als regulärer Ausdruck interpretiert. Für eine +wortgetreue Suche kann `-g` (Glob) verwendet werden. + +## Nach Namen suchen + +```bash +fd report # enthält "report" im Namen +fd -i report # ausdrücklich ohne Beachtung der Großschreibung +fd -g '*.pdf' # Glob-Muster, alle PDF-Dateien +fd -e pdf # nach der Endung pdf +fd -e jpg -e png # mehrere Endungen +fd -t f -e log # nur Dateien mit der Endung log +fd -t d config # nur Verzeichnisse mit "config" im Namen +fd -H '.env' # versteckte Dateien einbeziehen +``` + +Bei Globs müssen Wildcards quotiert werden, damit die Shell sie nicht vorab +expandiert. `-e pdf` ist meist angenehmer als `-g '*.pdf'`, weil die Endung +ohne Punkt angegeben wird. + +### Reguläre Ausdrücke + +```bash +fd '^README' # Namen, die mit README beginnen +fd 'v[0-9]+\.tar\.gz$' # z. B. v1.tar.gz +fd -I 'node_modules|target' # auch ignorierte Dateien suchen +fd -g 'bild-??.jpg' # Glob: genau zwei Zeichen vor .jpg +``` + +Mehrere Suchpfade sind möglich: + +```bash +fd -t f -e md ~/Dokumente ~/Projekte +``` + +## Suchbereich einschränken + +```bash +fd -d 1 # nur direkt unterhalb des aktuellen Ordners +fd -d 3 -e log # höchstens drei Ebenen tief +fd -E node_modules # node_modules ausschließen +fd -E '*.min.js' # Dateien per Glob ausschließen +fd -E .git -E build # mehrere Ausschlüsse +fd -p 'src/lib' # Muster als vollständigen Pfad behandeln +fd -a report # absolute Pfade ausgeben +``` + +Standardmäßig werden versteckte Pfade, `.gitignore`-Treffer und `.git` +Verzeichnisse ausgelassen. Das Verhalten lässt sich mit diesen Optionen ändern: + +```bash +fd -H pattern # versteckte Dateien einbeziehen +fd -I pattern # ignorierte Dateien einbeziehen +fd -u pattern # unbeschränkte Suche: versteckt + ignoriert +``` + +## Dateitypen und Eigenschaften + +```bash +fd -t f # reguläre Dateien +fd -t d # Verzeichnisse +fd -t l # symbolische Links +fd -t x # ausführbare Dateien +fd -t e # leere Dateien oder Verzeichnisse +fd -S +100M -t f # Dateien größer als 100 MB +fd -S -10k -t f # Dateien kleiner als 10 KB +fd --changed-within 7d # in den letzten sieben Tagen geändert +fd --changed-before 30d # vor mehr als 30 Tagen geändert +``` + +Größen-Suffixe sind unter anderem `k`, `M`, `G` und `T`. Zeitangaben können +beispielsweise `10m`, `2h`, `7d` oder `1w` sein. Die genaue Unterstützung hängt +von der installierten `fd`-Version ab; `fd --help` zeigt die verfügbaren +Optionen. + +## Ausgabe und Zählen + +```bash +fd -l pattern # Long-Format wie bei ls +fd --color never pattern # ohne ANSI-Farbcodes +fd --print0 -e jpg # NUL-separiert, sicher für Sonderzeichen +fd -e log | wc -l # Treffer zählen +fd -e log | sort # Treffer sortieren +fd -e log | xargs -r grep -n ERROR +``` + +Für robuste Pipelines mit beliebigen Dateinamen immer `--print0` zusammen mit +`xargs -0` verwenden: + +```bash +fd -0 -t f -e txt | xargs -0 -r wc -l +``` + +## Befehle auf Treffer anwenden + +`-x` führt einen Befehl für jeden Treffer aus. `{}` ist der Platzhalter für den +aktuellen Pfad: + +```bash +fd -t f -e sh -x chmod +x '{}' +fd -t f -e log -x gzip '{}' +fd -t f -e txt -x grep -nH 'TODO' '{}' +``` + +`-X` übergibt alle Treffer gemeinsam an den Befehl. Das ist für Programme +geeignet, die mehrere Dateien in einem Aufruf verarbeiten können: + +```bash +fd -t f -e jpg -X identify +fd -t f -e sh -X shellcheck +``` + +Vor einer Aktion zuerst einen Dry-Run ausführen: + +```bash +fd -t f -e tmp -x echo rm -- '{}' +fd -t f -e jpg -x echo cp -- '{}' ~/Bilder/ +``` + +`--` trennt Optionen des externen Befehls vom Dateinamen. Die Quoting-Regeln +des Beispiels schützen auch Dateinamen mit Leerzeichen. + +## Dateien kopieren, verschieben und löschen + +### Löschen + +```bash +# Treffer prüfen +fd -t f -e tmp + +# Dry-Run +fd -t f -e tmp -x echo rm -- '{}' + +# Tatsächlich löschen +fd -t f -e tmp -x rm -- '{}' +``` + +Leere Verzeichnisse: + +```bash +fd -t d -e old -x echo rmdir -- '{}' +fd -t d -e old -x rmdir -- '{}' +``` + +`rmdir` löscht nur leere Verzeichnisse. Für nichtleere Verzeichnisse wäre +`rm -r` erforderlich und sollte besonders vorsichtig eingesetzt werden. + +### Kopieren + +```bash +mkdir -p ~/Archiv/logs +fd -t f -e log -x echo cp -n -- '{}' ~/Archiv/logs/ +fd -t f -e log -x cp -n -- '{}' ~/Archiv/logs/ +``` + +`cp -n` verhindert das Überschreiben vorhandener Dateien. Für das Beibehalten +von Zeitstempeln und Berechtigungen kann `cp -p` ergänzt werden. + +### Verschieben + +```bash +mkdir -p ~/Archiv/alte-logs +fd -t f -e log --changed-before 30d -x echo mv -i -- '{}' ~/Archiv/alte-logs/ +fd -t f -e log --changed-before 30d -x mv -i -- '{}' ~/Archiv/alte-logs/ +``` + +`mv -i` fragt vor dem Überschreiben nach. Mit `mv -n` werden bestehende +Zieldateien ohne Rückfrage nicht ersetzt. + +## Dateien gesammelt umbenennen + +Für einfache Ersetzungen ist `mv` mit Shell-Parameterexpansion ausreichend. +Zuerst die geplanten Befehle anzeigen: + +```bash +fd -t f -e jpeg -x sh -c 'for f do printf "mv -- %q %q\\n" "$f" "${f%.jpeg}.jpg"; done' sh +``` + +Wenn das Ergebnis stimmt: + +```bash +fd -t f -e jpeg -x sh -c 'for f do mv -i -- "$f" "${f%.jpeg}.jpg"; done' sh +``` + +Weitere Beispiele für Namensänderungen: + +```bash +# Suffix _alt ergänzen +fd -t f -e txt -x sh -c 'for f do mv -i -- "$f" "${f%.txt}_alt.txt"; done' sh + +# Präfix backup- ergänzen +fd -t f -e conf -x sh -c 'for f do mv -i -- "$f" "$(dirname "$f")/backup-$(basename "$f")"; done' sh +``` + +Bei vielen Umbenennungen ist `-x` mit einer kleinen Shell-Schleife sicherer +als eine Pipe, weil Dateinamen nicht an Leerzeichen oder Zeilenumbrüchen +aufgeteilt werden. + +## Bulk-Bearbeitung von Dateien + +### Textdateien mit sed bearbeiten + +```bash +# Erst anzeigen, welche Dateien betroffen sind +fd -t f -e conf -e cfg + +# Dry-Run: Ausgabe prüfen, Dateien bleiben unverändert +fd -t f -e conf -e cfg -x sh -c 'for f do sed "s/alt/neu/g" "$f" > "$f.tmp" && diff -u "$f" "$f.tmp"; rm -- "$f.tmp"; done' sh + +# In-place mit Backup-Datei +fd -t f -e conf -e cfg -x sed -i.bak 's/alt/neu/g' '{}' +``` + +### Dateinamen mit Textsuche kombinieren + +```bash +fd -t f -e md -x rg -nH 'TODO|FIXME' '{}' +fd -t f -e log -x sh -c 'for f do grep -l ERROR "$f"; done' sh +``` + +### Dateien anhand des Namens einsortieren + +```bash +mkdir -p ~/Sortiert/{pdf,bilder} + +# Dry-Run +fd -t f -e pdf -x echo mv -i -- '{}' ~/Sortiert/pdf/ +fd -t f -e jpg -e png -x echo mv -i -- '{}' ~/Sortiert/bilder/ + +# Ausführen +fd -t f -e pdf -x mv -i -- '{}' ~/Sortiert/pdf/ +fd -t f -e jpg -e png -x mv -i -- '{}' ~/Sortiert/bilder/ +``` + +### Robuste Schleife mit NUL-Trennung + +Wenn zusätzlich komplexe Shell-Logik oder mehrere Variablen benötigt werden, +ist eine NUL-separierte Schleife eine gute Alternative: + +```bash +while IFS= read -r -d '' file; do + printf 'Bearbeite: %s\n' "$file" + # command -- "$file" +done < <(fd -0 -t f -e txt) +``` + +## Praktische Anwendungsfälle + +```bash +# Die zehn größten Dateien unterhalb des aktuellen Ordners +fd -t f -S +1M -x du -h '{}' | sort -rh | head -10 + +# Alle ausführbaren Shell-Skripte finden +fd -t x -e sh + +# Backups und temporäre Dateien ausschließen +fd -t f -E '*.bak' -E '*.tmp' -E .cache + +# Markdown-Dateien der letzten Woche archivieren +fd -t f -e md --changed-within 7d -X tar -czf aktuelle-doku.tar.gz + +# Prüfsummen für ISO-Dateien erzeugen +fd -t f -e iso -x sha256sum '{}' +``` + +Bei `fd -X` werden die Treffer als Argumente an `tar` übergeben. Für sehr +große Trefferlisten kann ein Befehl durch die Systemgrenze für Argumente +begrenzt sein; dann besser `fd -0` mit `xargs -0` oder `tar`-Optionen für +Dateilisten verwenden. + +## Vergleich mit find + +| Aufgabe | `find` | `fd` | +|---------|--------|------| +| Alle Logs finden | `find . -type f -name '*.log'` | `fd -t f -e log` | +| Verzeichnis suchen | `find . -type d -name 'src'` | `fd -t d src` | +| Tiefe begrenzen | `find . -maxdepth 2` | `fd -d 2` | +| Verzeichnis ausschließen | `find . -path './node_modules' -prune` | `fd -E node_modules` | +| Befehl ausführen | `find . -type f -exec cmd {} +` | `fd -t f -X cmd` | +| Änderungszeit | `find . -mtime -7` | `fd --changed-within 7d` | + +Komplexe Bedingungen nach Besitzer, Berechtigungen oder exakten Zeitstempeln +bleiben eine Stärke von `find`. + +## Wichtige Optionen + +| Option | Bedeutung | +|--------|-----------| +| `-t f` | nur reguläre Dateien | +| `-t d` | nur Verzeichnisse | +| `-t l` | nur symbolische Links | +| `-e EXT` | Dateiendung suchen | +| `-g` | Glob statt regulärem Ausdruck verwenden | +| `-i` | Groß-/Kleinschreibung ignorieren | +| `-H` | versteckte Dateien einbeziehen | +| `-I` | Git-ignorierte Dateien einbeziehen | +| `-u` | versteckte und ignorierte Dateien einbeziehen | +| `-d N` | maximale Tiefe | +| `-E PATH` | Pfad oder Muster ausschließen | +| `-a` | absolute Pfade ausgeben | +| `-0` / `--print0` | NUL-separierte Ausgabe | +| `-x CMD` | Befehl pro Treffer ausführen | +| `-X CMD` | Befehl mit allen Treffern ausführen | +| `-S SIZE` | nach Dateigröße filtern | + +## Best Practices + +1. Zuerst nur `fd ...` ausführen und die Treffer kontrollieren. +2. Vor Änderungen `-x echo ...` als Dry-Run verwenden. +3. Dateipfade immer quoten: `"$file"` oder `'{}'`. +4. Bei Pipes für beliebige Dateinamen `-0` und `xargs -0` verwenden. +5. Bei `rm` und `mv` `--` vor dem Dateipfad setzen. +6. Für Lösch-, Verschiebe- und Umbenennungsaktionen Backups oder Versionskontrolle nutzen. +7. Mit `fd --help` prüfen, welche Optionen die installierte Version unterstützt. + +## Siehe auch + +- [[IT-Know-How/Linux/BASH Basics/find]] - Klassische Dateisuche mit find +- [[IT-Know-How/Linux/BASH Basics/grep]] - Textsuche in Dateien +- [[IT-Know-How/Linux/BASH Basics/sed]] - Textdateien gesammelt bearbeiten +- [[IT-Know-How/Linux/BASH Basics/awk]] - Textverarbeitung und Datenextraktion +- [[IT-Know-How/Linux/BASH Basics/Dateiberechtigungen]] - chmod und chown +- [[IT-Know-How/Linux/BASH Basics/rsync]] - Dateien synchronisieren