finde xargs rm mit Dateinamenmuster in Variable

finde xargs rm mit Dateinamenmuster in Variable

Befehl wie dieser:

find /directory -type f -name "*.txt" -print | xargs rm

löscht jede .txtDatei im Verzeichnis und den Unterverzeichnissen, und das ist ok. Aber wenn wir eine Variable oder ein Array für die Dateierweiterung erstellen und dann findz. B.

TXT=(*.txt)
for ii in ${TXT[@]}; do
  find /directory -type f -name $TXT -print | xargs rm
done

Diese Befehle löschen keine .txtDateien in Unterverzeichnissen. Warum? Wie kann ich diesen zweiten Code ändern, um Dateien in Unterverzeichnissen zu löschen?

PS: Ich habe ein Array verwendet, weil ich mehr als eine Dateierweiterung habe.

Antwort1

Ihre Array-Zuordnung,

TXT=(*.txt)

erweitert das *.txtMuster auf die Liste der Dateinamen im aktuellen Verzeichnis, die diesem Muster entsprechen. Die Shell würde dies zum Zeitpunkt der Zuweisung tun. Das ist nicht das, was Sie wollen. Sie möchten findden wörtlichen String *.txtwie folgt angeben:

pattern='*.txt'
find /directory -type f -name "$pattern" -exec rm {} +

Hier habe ich auch entfernt xargs rmund führe stattdessen rmdirekt von aus find. Die meisten aktuellen Implementierungen von könnten anstelle von finddas nicht standardmäßige verwenden :-delete-exec rm {} +

pattern='*.txt'
find /directory -type f -name "$pattern" -delete

Beachten Sie, dass hier keine Schleife erforderlich ist, da wir nur mit einem einzigen Muster arbeiten. Beachten Sie auch, dass die Anführungszeichen "$pattern"im Aufruf von findwichtig sind, da das Muster sonst vor dem Start durch alle passenden Dateinamen im aktuellen Verzeichnis ersetzt würde find.

Für verschiedene Muster könnten Sie eine Schleife wie folgt ausführen:

patterns=( '*.txt' '*.tmp' )
for pattern in "${patterns[@]}"; do
    find /directory -type f -name "$pattern" -delete
done

Die Anführungszeichen in der Array-Zuweisung sind wichtig, da sie verhindern, dass die Shell die Muster sofort als Muster zum Globbing von Dateinamen verwendet. Aus demselben Grund sind auch die Anführungszeichen von "${patterns[@]}"und wichtig."$pattern"

Ein anderer Ansatz besteht darin, nur einen einzigen Aufruf von durchzuführen find, selbst wenn Sie mehrere Muster haben. Dies würde die Dinge erheblich beschleunigen, wenn es /directorysich um eine große Verzeichnishierarchie handelt. Der folgende Code tut dies, indem er ein Array von -nameTests für erstellt, die findverwendet werden sollen:

patterns=( '*.txt' '*.tmp' )

name_tests=( )
for pattern in "${patterns[@]}"; do
    name_tests+=( -o -name "$pattern" )
done

# "${name_tests[@]:1}" removes the initial "-o", which shouldn't be there.
name_tests=( '(' "${name_tests[@]:1}" ')' )

find /directory -type f "${name_tests[@]}" -delete

Im obigen Skript wird am Ende der eigentliche Befehl ausgeführt:

find /directory -type f '(' -name '*.txt' -o -name '*.tmp' ')' -delete

... wodurch alle regulären Dateien mit Dateinamensuffixen gelöscht werden.txt oder .tmpirgendwo im oder unterhalb des Verzeichnisses /directory.

verwandte Informationen