Ich muss ein Verzeichnis rekursiv durchlaufen und alle Dateien mit der Erweiterung .pdf
und entfernen .doc
. Ich schaffe es, ein Verzeichnis rekursiv zu durchlaufen, aber nicht die Dateien mit den oben genannten Dateierweiterungen zu filtern.
Mein Code bisher
#/bin/sh
SEARCH_FOLDER="/tmp/*"
for f in $SEARCH_FOLDER
do
if [ -d "$f" ]
then
for ff in $f/*
do
echo "Processing $ff"
done
else
echo "Processing file $f"
fi
done
Ich brauche Hilfe, um den Code zu vervollständigen, da ich nicht weiterkomme.
rm
ein Teil des OP-Codes ist, aber es ist für die gestellte Frage nicht wirklich relevant. Ich denke, es wäre sicherer, wenn die Antworten mit einem harmlosen Befehl wie formuliert würdenecho
.Antworten:
find
ist nur dafür gemacht.quelle
-delete
Option.find ... -print0 | xargs -0 ...
, nicht rohen Fund | xargs, um Probleme mit Dateinamen zu vermeiden, die Zeilenumbrüche enthalten.xargs
ohne Optionen ist fast immer ein schlechter Rat, und dies ist keine Ausnahme. Verwenden Siefind … -exec
stattdessen.Als Folge der Antwort von mouviciel können Sie dies auch als for-Schleife ausführen, anstatt xargs zu verwenden. Ich finde xargs oft umständlich, besonders wenn ich in jeder Iteration etwas Komplizierteres tun muss.
Wie einige Leute kommentiert haben, schlägt dies fehl, wenn die Dateinamen Leerzeichen enthalten. Sie können dies umgehen, indem Sie den IFS (Internal Field Separator) vorübergehend auf das Zeilenumbruchzeichen setzen. Dies schlägt auch fehl, wenn
\[?*
die Dateinamen Platzhalterzeichen enthalten. Sie können dies umgehen, indem Sie die Platzhaltererweiterung (Globbing) vorübergehend deaktivieren.Wenn Ihre Dateinamen Zeilenumbrüche enthalten, funktioniert dies auch nicht. Mit einer xargs-basierten Lösung sind Sie besser dran:
(Die mit Klammern versehenen Klammern müssen hier
-print0
für beideor
Klauseln gelten.)GNU und * BSD find haben auch eine
-delete
Aktion, die so aussehen würde:quelle
for f in $(find ...)
. Verwenden Sie diese Methode einfach nicht.Ohne
find
:/tmp/*
sind Dateien im Verzeichnis und/tmp/**/*
sind Dateien in Unterordnern. Möglicherweise müssen Sie die globstar-Option (shopt -s globstar
) aktivieren . Für die Frage sollte der Code also so aussehen:Beachten Sie, dass dies Bash ≥ 4.0 erfordert (oder zsh ohne
shopt -s globstar
oder ksh mitset -o globstar
stattshopt -s globstar
). Darüber hinaus werden in bash <4.3 symbolische Verknüpfungen zu Verzeichnissen sowie zu Verzeichnissen durchlaufen, was normalerweise nicht wünschenswert ist.quelle
for f in /tmp/**
wird ausreichen. Enthält die Dateien aus dem Verzeichnis / tmp.for f in /tmp/*.{pdf,doc} tmp/**/*.{,pdf,doc} ; do
**
ist eine schöne Erweiterung, aber nicht portabel für POSIXsh
. (Diese Frage ist mit bash markiert, aber es wäre schön darauf hinzuweisen, dass dies im Gegensatz zu einigen der hier aufgeführten Lösungen wirklich nur Bash ist. Oder sie funktioniert auch in mehreren anderen erweiterten Shells.)Wenn Sie etwas rekursiv tun möchten, empfehle ich Ihnen, die Rekursion zu verwenden (ja, Sie können dies mit Stapeln usw. tun, aber hey).
Das heißt,
find
ist wahrscheinlich eine bessere Wahl, als bereits vorgeschlagen wurde.quelle
Hier ist ein Beispiel mit shell (
bash
):quelle
Dies beantwortet Ihre Frage nicht direkt, aber Sie können Ihr Problem mit einem Einzeiler lösen:
Einige Versionen von find (GNU, BSD) verfügen über eine
-delete
Aktion, die Sie verwenden können, anstatt Folgendes aufzurufenrm
:quelle
Diese Methode behandelt Leerzeichen gut.
Bearbeiten, Korrekturen nacheinander
quelle
Für Bash (seit Version 4.0):
Das ist alles.
Die nachfolgende Erweiterung ".ext", um Dateien (oder Verzeichnisse) mit dieser Erweiterung auszuwählen.
Option globstar aktiviert das ** (Suche rekursiv).
Die Option nullglob entfernt ein *, wenn es keiner Datei / keinem Verzeichnis entspricht.
Option dotglob enthält Dateien, die mit einem Punkt beginnen (versteckte Dateien).
Beachten Sie, dass vor Bash 4.3
**/
auch symbolische Links zu Verzeichnissen durchlaufen werden, was nicht wünschenswert ist.quelle
Die folgende Funktion würde rekursiv alle Verzeichnisse im
\home\ubuntu
Verzeichnis durchlaufen (gesamte Verzeichnisstruktur unter Ubuntu) und die erforderlichen Prüfungen imelse
Block anwenden .quelle
Dies ist der einfachste Weg, den ich kenne, um dies zu tun:
rm **/@(*.doc|*.pdf)
**
macht diese Arbeit rekursiv@(*.doc|*.pdf)
sucht nach einer Datei, die auf pdf OR doc endetEinfach sicher zu testen durch Ersetzen
rm
durchls
quelle
Es gibt keinen Grund, die Ausgabe von
find
an ein anderes Dienstprogramm weiterzuleiten.find
hat eine-delete
Flagge eingebaut.quelle
Die anderen Antworten enthalten keine Dateien oder Verzeichnisse, die mit a beginnen. Folgendes hat bei mir funktioniert:
quelle
Mach einfach
quelle
Im Folgenden wird das angegebene Verzeichnis rekursiv durchlaufen und der gesamte Inhalt aufgelistet:
for d in /home/ubuntu/*; do echo "listing contents of dir: $d"; ls -l $d/; done
quelle
ls -l /home/ubuntu/*/
, also ist es ziemlich nutzlos.Wenn Sie die zum Ausführen des Befehls verwendete Shell ändern können, können Sie den Job mit ZSH ausführen.
Dadurch werden alle Dateien / Ordner rekursiv durchlaufen.
quelle