Wie kann ich mkdir anweisen, zu versuchen, dir1 zu erstellen, und wenn es bereits existiert, erstelle dir2 usw., bis es auf einen Namen trifft, der nicht existiert?

4746
01AutoMonkey

Ich möchte ein Verzeichnis mit einer Nummer am Ende, ex "dir1", erstellen und diese Nummer erhöhen, wenn das Verzeichnis bereits vorhanden ist, bis es auf einen Verzeichnisnamen trifft, der nicht existiert, und ich muss dies in einer einzigen Zeile tun eine Linux-Befehlszeile, etwa:

mkdir --increment dir$ 

Wie würde ich das machen?

Bisher habe ich folgendes bekommen:

dir=output; n=0; mkdir -p $dir$n; if test -d $dir$n; then n=$((n+1)); echo $dir$n; fi 

Es ist jedoch nur der Name des nächsten Verzeichnisses. Ich brauche es, um den Befehl rekursiv auszuführen.

13

5 Antworten auf die Frage

26
JdeBP

Dies ist eine triviale Übung bei der Verwendung von while:

n = 0 während! mkdir dir $ n tun n = $ ((n + 1)) erledigt

Natürlich braucht man nicht lange darüber nachzudenken, dass dieser triviale Mechanismus nicht gut skalierbar ist.

Anstatt das Rad neu zu erfinden und alle Ecken erneut abzurasieren, werden aus einer Vorlage eindeutige temporäre Verzeichnisse erstellt, die etwas anders aussehen:

name = $ (mktemp -d dirXXXXXXXXXXX)

Die binäre Suche nach der Nummer ist möglicherweise gut genug. Thorbjørn Ravn Andersen vor 10 Jahren 0
Es gibt ein paar Ecken und Kanten, von denen Sie sich bei der Neuerfindung der Räder abschneiden müssen. Nicht zuletzt erinnern sie sich an das Dateisystem, wenn es um Sicherheit und Parallelisierung geht. JdeBP vor 10 Jahren 0
5
glenn jackman

Finden Sie zuerst den "größten" Verzeichnisnamen, holen Sie sich die Nummer und erhöhen Sie diese:

last_dir=(printf "%s\n" dir* | sort -Vr | head -1) num=$(last_dir#dir) mkdir "dir$((num+1))" 
Dies ist eine gute Idee, die jedoch nicht leicht zu parallelisieren ist. Thorbjørn Ravn Andersen vor 10 Jahren 0
Wenn es nicht Millionen von Verzeichnissen gibt, ist Parallelisierung definitiv eine vorzeitige Optimierung. glenn jackman vor 10 Jahren 0
Warum brauchen Sie hier 'printf'? Wird nicht einfach ein "Echo" funktionieren? Ruslan vor 10 Jahren 0
Ich würde auch "dir [0-9] *" anstelle von "dir *" verwenden. Ruslan vor 10 Jahren 0
Sie missverstehen. Ich spreche darüber, ob es sinnvoll ist, das Skript mehrmals gleichzeitig auszuführen (mehrere Threads, mehrere Benutzer usw.) oder nicht. Thorbjørn Ravn Andersen vor 10 Jahren 1
@Ruslan, Sortierung benötigt einen Dateinamen pro Zeile. echo gibt nur die Dateinamen mit Leerzeichen aus. Beachten Sie, dass `dir [0-9] *` immer noch mit "dir1a" übereinstimmt. Für "dir gefolgt von Zahlen" können wir folgendes tun: `shopt -s extglob; printf "% s \ n" dir + ([0-9]) ` glenn jackman vor 10 Jahren 0
4
IQAndreas

Wenn Sie nur inkrementell Verzeichnisse erstellen möchten, die in der richtigen Reihenfolge aufgeführt sind, kann ich stattdessen Ordner empfehlen, deren Namen auf dem aktuellen Datum basieren.

DATE=$(date +%F) mkdir "dir-$DATE" 

Es werden Verzeichnisse mit Namen erstellt dir-2014-03-02( YYYY-MM-DDso, dass sie in alphabetischer Reihenfolge erscheinen).

Wenn Sie mehr als ein Verzeichnis pro Tag erstellen, können Sie die aktuelle Uhrzeit zum Dateinamen hinzufügen. Sehen Sie man date, wie Sie die Ausgabe Formatierung zwicken date.

2
davidgo

Angenommen, Ihre Verzeichnisse beginnen immer mit "dir1", und es gibt keine Dateien mit dem Namen $ dir * (d. H. Sie sind alle sequenziell nummerierte Verzeichnisse).

mkdir $$(( `ls $* | wc -w` + 1 )) 

Dies zählt die Anzahl der Dateien, die mit $ dir beginnen, addiert dann eine zu dieser Anzahl und erstellt eine neue Datei.

0
Joe

Nachtrag zu den anderen Antworten: Wenn Sie die Verzeichnisse korrekt nach Namen sortieren möchten, können Sie die neue Verzeichnisnummer (NUM) mit führenden Nullen auf eine feste Länge auffüllen.

Das Folgende könnte auf einer Leitung zusammengefasst oder in eine der anderen Lösungen eingebettet sein.

NUM="00"$NUM ## Left zero pad with fixed length - 1 zeros  NUM=$ - 3)):3} ## left trim to fixed length (3 in this case) 

Dies setzt voraus, dass NUM mindestens eine Ziffer lang beginnt und die feste Länge nicht überschreitet. Passen Sie entsprechend Ihren Anforderungen an.