Ich habe folderA
das hat einige Dateien mit einer Nummernfolge beginnend mit a_000000
. Was ich tun möchte, ist, Dateien ab einer bestimmten Nummer zu löschen: Sagen wir, a_000750
bis zum Ende der Dateien in dieser folderA
. Könnte jemand bitte beraten, wie dies mit Shell-Skript zu tun ist?
16
rm a_000[89]* a_0007[5-9]*
?a_000[89]*
enthält jede Datei, die mita_0008
oder beginnta_0009
, unda_0007[5-9]*
enthält jede Datei, die mita_0007
und dann mit einer Zahl zwischen 5 und 9 beginnt , gefolgt von einer beliebigen Zahl.Antworten:
Vorausgesetzt, Sie kennen das Ende des Bereichs oder können es erraten, könnten Sie Klammererweiterungen verwenden :
Mit dem obigen Befehl werden die 101 Dateien zwischen a_000750 und a_000850 einschließlich gelöscht (und es werden Dateinamen beanstandet, die auf nicht vorhandene Dateien verweisen). Wenn Sie zu viele Dateien dafür haben, verwenden Sie
find
:Hier werden
find
einfach alle passenden Dateien aufgelisteta_*
. Die Liste wird an einewhile
Schleife übergeben, in der jeder Dateiname in die Variable eingelesen wird$file
. Wenn der numerische Teil (Find druckt Dateien als , druckt also nur die Zahl) oder größer ist, wird die Datei mithilfe der Zeichenfolgenmanipulationsfunktionen von bash gelöscht. Das ist einfach da, damit Sie sehen können, welche Dateien entfernt wurden../file
${file#./a_}
000750
-v
Beachten Sie, dass das oben Gesagte Dateinamen voraussetzt. Wenn Ihre Namen Leerzeichen, Zeilenumbrüche oder andere seltsame Zeichen enthalten können, verwenden Sie stattdessen Folgendes:
quelle
[[
?[[
Vereinfacht hier[[ "${file#./a_}" > 000749 ]]
zum Beispiel nicht, verkürzt es auch nicht. Ich verwende keine unnötige Syntax und diese funktioniert sogar in einfacheren Shells wiedash
.[[
ich mit Leerzeichen und Verrücktheiten besser umgehen kann (ich mag auch nicht viel>
).[
ist in Ordnung, wenn Sie die Variable wie ich zitieren, funktioniert auf weit mehr Shells und ist einfacher.Sie könnten so etwas tun:
Oder:
Die erste Methode nimmt ein festes Präfix an, entfernt es und überprüft den Wert.
Die zweite Methode setzt ein Suffix fester Länge (und ein gemeinsames festes Präfix) voraus und stützt sich auf diese Tatsache. und das, während es in lexikographischer
201
Hinsicht vorher kommt, vorher31
nicht031
.Testen Sie dies mit dem
echo
Befehl, und verwenden Sierm
stattdessen , wenn Sie sicher sind, dass die richtigen Dateien aufgeführt sind .quelle
POSIX-Shell-Lösung
Die erste Lösung von terdon basiert auf der Klammererweiterung , die eine Eigenschaft von ist
bash
undksh
jedoch nicht in der Standard-/bin/sh
Shell verwendet werden kann, mit der Ubuntu verknüpft ist/bin/dash
.In Fällen, in denen Sie sich auf die
/bin/sh
Portabilität Ihrer Skripte verlassen müssen, gibt es im Allgemeinen zwei Möglichkeiten, um dies zu erreichen. Man würde über Globbing sein. Geradecd folderA
und von dort laufenrm a_*
. Die andere Möglichkeit wäre die Implementierung einer C-ähnlichen for-Loop-Alternativewhile <CONDITION>;do ...done
in der Shell-Sprache und das Formatieren der Zahlen mitprintf
:Beachten Sie, dass ich hier verwende
echo
. Ersetzen Sieecho "$filename"
durchrm ./"$filename"
oder,rm -- "$filename"
wenn Sie bereit sind, die Dateien zu löschen. Beachten Sie auch, dass dies durchgeführt werden sollte, wenn Sie sich bereitscd
in dem gewünschten Verzeichnis angemeldet haben.(ab) awk benutzen
Awk, eine nette C-ähnliche Sprache, kann uns auf zwei Arten helfen: (1) Wir können Dateinamen mit for-loop generieren und sie über die
sprintf
Funktion formatieren und (2) die Dateien über einensystem()
Befehl löschen , der unseren generierten Dateinamen undrm
Befehl übergibt zu/bin/sh
:Perl
Weiter mit der Idee des portablen Ansatzes, bei dem wir Dateinamen "generieren", können wir dasselbe in Perl tun:
quelle
So einfach wie
In deinem Beispiel ist es
quelle
a_00075
... beginnen