Wie kann ich mkdir anweisen, dir1 zu erstellen und, falls es bereits existiert, dir2 usw. zu erstellen, bis es auf einen Namen stößt, der nicht existiert?

13

Ich möchte ein Verzeichnis mit einer Nummer am Ende erstellen, z. "dir1", und erhöhen Sie diese Zahl, wenn das Verzeichnis bereits vorhanden ist, bis es auf einen nicht vorhandenen Verzeichnisnamen stößt. Dies muss in einer einzelnen Zeile in einer Linux-Befehlszeile erfolgen.

mkdir --increment dir$

Wie würde ich das machen?

Bisher habe ich folgendes:

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

Aber es gibt nur den Namen des nächsten Verzeichnisses wieder. Ich brauche ihn, um den Befehl rekursiv auszuführen.

01AutoMonkey
quelle

Antworten:

26

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

n=0
while ! mkdir dir$n
do
    n=$((n+1))
done

Aber natürlich braucht man nicht viel nachzudenken, um zu erkennen, dass dieser triviale Mechanismus nicht gut skaliert.

Anstatt das Rad neu zu erfinden und alle Ecken erneut abzurasieren, erstellt man aus einer Vorlage ein eindeutiges temporäres Verzeichnis:

name=$(mktemp -d dirXXXXXXXXXXX)
JdeBP
quelle
Eine binäre Suche nach der Nummer ist möglicherweise ausreichend.
Thorbjørn Ravn Andersen
Es gibt eine ganze Reihe von Abschnitten, an denen Sie die Neuerfindung des Rads beginnen müssen. Nicht zuletzt müssen Sie sich unter Berücksichtigung der Sicherheit und der Parallelisierung an das Dateisystem erinnern.
JdeBP
6

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 den Namen wie erstellt dir-2014-03-02 ( YYYY-MM-DD, um in alphabetischer Reihenfolge angezeigt zu werden).

Wenn Sie mehr als ein Verzeichnis pro Tag erstellen, können Sie die aktuelle Uhrzeit zum Dateinamen hinzufügen. Sehen man date zum Optimieren der Ausgabeformatierung von date.

IQAndreas
quelle
5

Finden Sie zuerst den "größten" Verzeichnisnamen, ermitteln Sie 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))"
glenn jackman
quelle
Dies ist eine gute Idee, lässt sich jedoch nicht leicht parallelisieren.
Thorbjørn Ravn Andersen
Wenn es nicht Millionen von Verzeichnissen gibt, ist Parallelisierung definitiv eine vorzeitige Optimierung.
glenn jackman
Warum würdest du brauchen printf Hier? Wird nicht einfach echo Arbeit?
Ruslan
Ich würde auch verwenden dir[0-9]* anstatt dir*.
Ruslan
1
Sie missverstehen. Ich spreche darüber, ob es sinnvoll ist, das Skript mehrere Male gleichzeitig auszuführen (mehrere Threads, mehrere Benutzer usw.) oder nicht.
Thorbjørn Ravn Andersen
2

Angenommen, Ihre Verzeichnisse beginnen immer mit "dir1", und es gibt keine Dateien mit dem Namen $ dir * (d. H. Alle Verzeichnisse sind fortlaufend nummeriert).

mkdir ${dir}$(( `ls ${dir}* | 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.

davidgo
quelle
0

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

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=${NUM:((${#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.

Joe
quelle