update
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user