Come faccio a dire a mkdir di provare a creare dir1, e se esiste già creare dir2, ecc, fino a quando non colpisce un nome che non esiste?


13

Voglio creare una directory con un numero alla fine, ex "dir1", e incrementare quel numero se la directory esiste già fino a quando non raggiunge un nome di directory che non esiste, e devo farlo in una sola riga in una riga di comando di Linux, qualcosa del tipo:

mkdir --increment dir$

Come potrei farlo?

Finora ho questo:

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

Ma riecheggia solo il nome della prossima directory, ne ho bisogno per eseguire ricorsivamente il comando.

Risposte:


26

Questo è un esercizio banale nell'uso di while:

n = 0
mentre ! mkdir dir $ n
fare
    n = $ ((n + 1))
fatto

Ma ovviamente non ci vuole molto a capire che questo banale meccanismo non si adatta bene.

Quindi, invece di reinventare la ruota e dover rasare di nuovo tutti gli angoli, si creano directory temporanee uniche da un modello leggermente diverso:

nome = $ (mktemp -d dirXXXXXXXXXXX)


La ricerca binaria sul numero potrebbe essere abbastanza buona.
Thorbjørn Ravn Andersen,

Ci sono alcuni angoli da cui partire per iniziare il processo di reinvenzione delle ruote, non ultimo il fatto di ricordare il filesystem, considerando la sicurezza e il parallelismo.
JdeBP

6

Se si desidera solo creare in modo incrementale directory elencate nell'ordine corretto, è possibile invece raccomandare cartelle denominate in base alla data corrente?

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

Creerà directory con i nomi simili dir-2014-03-02( YYYY-MM-DD, in modo da apparire in ordine alfabetico).

Se si crea più di una directory al giorno, è possibile aggiungere l'ora corrente al nome del file. Scopri man datecome modificare la formattazione dell'output di date.


5

trova prima il dirname "più grande", ottieni il numero e incrementa quello:

last_dir=(printf "%s\n" dir* | sort -Vr | head -1)
num=$(last_dir#dir)
mkdir "dir$((num+1))"

Questa è una buona idea, ma non è facile parallelizzare.
Thorbjørn Ravn Andersen,

A meno che non ci siano milioni di directory, la parallelizzazione è sicuramente un'ottimizzazione prematura.
Glenn Jackman,

Perché dovresti aver bisogno printfqui? Non sarà un echolavoro semplice ?
Ruslan

Inoltre, userei dir[0-9]*invece di dir*.
Ruslan,

1
Tu fraintendi. Parlo del fatto che lo script sia sensato per essere eseguito più volte contemporaneamente (più thread, più utenti ecc.) Oppure no.
Thorbjørn Ravn Andersen,

2

Supponendo che le tue directory inizino sempre da "dir1" e che non ci siano file denominati $ dir * (cioè sono tutte directory numerate in sequenza), puoi cavartela con questa riga -

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

Questo conta il numero di file che iniziano con $ dir, quindi ne aggiunge uno a quel numero e crea un nuovo file.


0

Addendum alle altre risposte: se hai bisogno che le directory siano ordinate correttamente per nome, potresti anche voler riempire il nuovo numero di directory (NUM) con zeri iniziali per una lunghezza fissa.

Quanto segue potrebbe essere condensato su una linea o incorporato in una delle altre soluzioni.

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)

Ciò presuppone che NUM inizi almeno una cifra e non superi la lunghezza fissa. Adeguarsi di conseguenza alle proprie esigenze.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.