¿Cómo le digo a mkdir que intente crear dir1, y si ya existe, cree dir2, etc., hasta que encuentre un nombre que no existe?

13

Quiero crear un directorio con un número al final, por ejemplo, "dir1", e incrementar ese número si el directorio ya existe hasta que llegue a un nombre de directorio que no existe, y necesito hacer esto en una sola línea en una línea de comando de Linux, algo como:

mkdir --increment dir$

¿Cómo voy a hacer eso?

Hasta ahora tengo esto:

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

Pero solo hace eco del siguiente nombre de directorio, lo necesito para ejecutar recursivamente el comando.

01AutoMonkey
fuente

Respuestas:

26

Este es un ejercicio trivial en el uso de while:

n = 0
mientras ! mkdir dir $ n
hacer
    n = $ ((n + 1))
hecho

Pero, por supuesto, no hace falta mucho pensar para darse cuenta de que este mecanismo trivial no escala bien.

Entonces, en lugar de reinventar la rueda y tener que afeitar todas las esquinas nuevamente, uno crea directorios temporales únicos a partir de una plantilla de manera ligeramente diferente:

nombre = $ (mktemp -d dirXXXXXXXXXXX)

JdeBP
fuente
La búsqueda binaria en el número puede ser lo suficientemente buena.
Thorbjørn Ravn Andersen
Hay bastantes esquinas para recortar desde donde está comenzando en el proceso de reinvención de la rueda, entre las cuales se encuentran el sistema de archivos, considerando la seguridad y la paralelización.
JdeBP
6

Si solo desea crear de forma incremental los directorios que se enumeran en el orden correcto, ¿puedo recomendar carpetas con nombres basados ​​en la fecha actual?

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

Creará directorios con los nombres like dir-2014-03-02( YYYY-MM-DDpara que aparezcan en orden alfabético).

Si crea más de un directorio por día, puede agregar la hora actual al nombre del archivo. Vea man datecómo ajustar el formato de salida de date.

IQAndreas
fuente
5

encuentre primero el nombre de directorio "más grande", obtenga el número e incremente eso:

last_dir=(printf "%s\n" dir* | sort -Vr | head -1)
num=$(last_dir#dir)
mkdir "dir$((num+1))"
Glenn Jackman
fuente
Esta es una buena idea, pero no es fácil paralizar.
Thorbjørn Ravn Andersen
A menos que haya millones de directorios, la paralelización es definitivamente una optimización prematura.
Glenn Jackman
¿Por qué necesitarías printfaquí? ¿No será un echotrabajo simple ?
Ruslan
Además, usaría en dir[0-9]*lugar de dir*.
Ruslan
1
Tu no entiendes. Hablo sobre si el script es sensible a ejecutarse varias veces a la vez (múltiples hilos, múltiples usuarios, etc.) o no.
Thorbjørn Ravn Andersen
2

Suponiendo que sus directorios siempre comienzan en "dir1", y que no hay archivos llamados $ dir * (es decir, todos son directorios numerados secuencialmente), puede salirse con esta frase:

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

Esto cuenta el número de archivos que comienzan con $ dir, luego agrega uno a ese número y crea un nuevo archivo.

davidgo
fuente
0

Anexo a las otras respuestas: si necesita que los directorios se ordenen correctamente por nombre, también puede rellenar el nuevo número de directorio (NUM) con ceros iniciales a una longitud fija.

Lo siguiente podría condensarse en una línea o incrustarse en una de las otras soluciones.

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)

Esto supone que NUM comienza al menos con 1 dígito de longitud y no excederá la longitud fija. Ajuste de acuerdo a sus requerimientos.

Joe
fuente