listet Dateien auf, die in einem bestimmten Bereich nummeriert sind

16

Ich habe eine Reihe von Dateien in einem Verzeichnis wie folgt nummeriert:

file1.txt
file2.txt
...
file30.txt
...

Jetzt möchte ich einen Befehl für einen bestimmten Bereich von Dateien ausführen, sagen wir 18 bis 31.

Bisher habe ich die folgenden Möglichkeiten verwendet,

drei Argumente

command file1[8-9].txt file2[0-9].txt file3[0-1].txt

Angenommen, ich möchte jede andere Nummer,

Schleife

for i in `jot - 18 31 2`; do echo file${i}.txt; done | xargs command

dies scheint eine zuverlässigere Schleife zu sein (Leerzeichen funktionieren)

for i in `jot - 18 31 2`; do echo "\"file${i}.txt\" "; done | xargs command

aber es scheint, als gäbe es einen einfacheren Weg, dies zu tun. Ich vermute, dass die beste Lösung darin besteht, eine Bash-Funktion zu erstellen, die den Dateisatz an die Befehlszeile zurückgibt. Dann könnte ich so etwas tun,

command `filerange file 18 31`

Gibt es bessere Wege oder Vorschläge, um dies effizient zu tun?

Ich entschuldige mich im Voraus, wenn ich die gleiche Frage verpasst habe, die irgendwo anders im Internet oder im Internet beantwortet wurde superuser.

Milchpfosten
quelle
Ich habe meine Frage so aktualisiert, dass sie eine Lösung enthält for, die mithilfe von xargs Leerzeichen in Dateinamen zulässt. Es scheint zu funktionieren, wenn Sie nicht Bash 4 haben. Wenn Sie Bash 4 haben, dann verwenden Sie definitiv die Klammererweiterung! Siehe die ausgewählte Antwort. Schamloser Plug für ein Upgrade von Snow Leopard bash
milkypostman

Antworten:

25

Versuche dies:

for file in file{18..31}.txt

Es ist als "Sequenzausdruck" bekannt und Teil von Bashs Klammererweiterung . Es funktioniert in Bash 3 und 4.

Die Inkrementierungsfunktion ist neu in Bash 4. Sie haben wahrscheinlich Bash 3.x.

In Bash 4 können Sie Folgendes tun:

$ for i in {1..6..2}; do echo $i; done
1
3
5

In Bash 3 müssen Sie dies jedoch tun, um die gleichen Ergebnisse zu erzielen:

$ for ((i=1; i<=6; i+=2)); do echo $i; done

Das gleiche Formular, inkrementiert um eins:

$ for ((i=1; i<=6; i++)); do echo $i; done

Jede der Zahlen kann eine Variable oder ein Ausdruck sein. In einem Sequenzausdruck müssen die Zahlen jedoch Konstanten sein

Hier ist ein Beispiel für die Verwendung dieses Formulars in Ihren Dateien:

for ((i=18; i<=31; i++))
do
    echo "file${i}.txt"
done

Ein weiteres neues Merkmal von Sequenzausdrücken in Bash 4 ist die Möglichkeit, führende Nullen einzufügen. Dies ist nützlich, wenn Sie nummerierte Dateien erstellen (und verwenden) möchten, die ordnungsgemäß sortiert werden können.

In Bash 4:

touch file{001..010}.txt

würde Dateien mit dem Namen "file001.txt" bis "file010.txt" erstellen. Ihre Namen werden in der erwarteten Reihenfolge sortiert. Ohne die führenden Nullen würde "file10.txt" vor "file1.txt" sortiert.

Um mit den Dateien zu arbeiten, können Sie dieselbe führende Null-Syntax verwenden:

for file in file{001..010}.txt; do echo "$file"; done

Wenn Sie in Bash 3 führende Nullen benötigen, müssen Sie den Wert selbst auffüllen:

for i in {1..10}
do
    printf -v i '%03d' $i 
    echo "file${i}.txt"
done

Das printf Anweisung wird dem Wert von i führende Nullen voranstellen, sodass die Breite beispielsweise 3 ist ("4" wird zu "004").

Bearbeiten:

Das Platzieren von Leerzeichen in Dateinamen ist unkompliziert:

$ touch "space name "{008..018..3}" more spaces"
$ ls -l sp*
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000008 more spaces
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000011 more spaces
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000014 more spaces
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000017 more spaces
$ for f in "space name "{008..018..3}" more spaces"; do mv "$f" "${f}.txt"; done
$ ls -l sp*
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000008 more spaces.txt
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000011 more spaces.txt
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000014 more spaces.txt
-rw-r--r-- 1 user group 0 2011-01-22 11:48 space name 000017 more spaces.txt
Bis auf weiteres angehalten.
quelle
Danke! Ich weiß nicht, wo das mein ganzes Leben lang war. Das einzige, was ich nicht zur Arbeit bringen kann, ist, dass das Inkrement in der OSX-Version von bash nicht zu funktionieren scheint. Das heißt, ich kann {1..10..2}mit meiner OSX-Bash nicht arbeiten.
Milchpfosten
Nun, es liegt daran, dass Snow Leopard (aus irgendeinem Grund) Bash 3.1 verwendet. Dies ist ein Softwareproblem.
Milchpfosten
@milkypostman: Die Inkrementierungsfunktion und die führenden Nullen {01..10}sind neu in Bash 4. Sie haben wahrscheinlich Bash 3.x. Wenn Sie die Inkrementierungsfunktion benötigen oder Variablen für die Bereichsgrenzen verwenden möchten, verwenden Sie dieses Formular: for ((i=1; i<=10; i+=2}(oder i++zum Inkrementieren um eins). Jede der Zahlen kann eine Variable oder ein Ausdruck sein. Verwenden Sie dann den Wert in der forSchleife: echo "file${i}.txt". In Bash 3, if you need leading zeros, inside the for loop do: printf -vi '% 03d' $ i ', der den Wert imit führenden Nullen voranstellt, sodass die Breite beispielsweise 3 beträgt ("4" wird zu "004").
Bis auf weiteres angehalten.
Dennis, gibt es eine Möglichkeit, Ihre Lösung so zu aktualisieren, dass sie das alternative Formular enthält. Ein Kommentar zu sein ist ein bisschen verschleiert, was ich wahrscheinlich bekommen soll.
Milchpfosten
@milkypostman: Siehe meine bearbeitete Antwort.
Bis auf weiteres angehalten.