Crear numerosos directorios usando mkdir

14

Me gustaría crear muchos directorios usando mkdir. Cada nombre de directorio consistirá en un prefijo (una cadena) y un índice (un entero). Suponga que me gustaría que el prefijo sea "s" y que los índices oscilen entre 1 y 50. Esto significa que me gustaría crear directorios titulados:

s1, s2, ..., s49,s50

¿Hay alguna manera de hacer esto automáticamente mkdir? Gracias por tu tiempo.

Andrés
fuente
2
¿Qué caparazón estás usando?
Francesco Turco
@FrancescoTurco que estoy usando bash. ¡Gracias por tu tiempo!
Andrew
3
Para su información, me resulta mucho más útil el uso de índices de ancho fijo, como: s01, s02, ..., s49, s50. Si utilicé índices de ancho fijo, /bin/lscasi siempre produce el orden que quiero.
Rob

Respuestas:

32

Puede hacer esto con un script de shell.

Pure sh: esto funcionará incluso en conchas de bourne pre POSIX

n=1;
max=50;
while [ "$n" -le "$max" ]; do
  mkdir "s$n"
  n=`expr "$n" + 1`;
done

Si desea crear una gran cantidad de directorios, puede hacer que la secuencia de comandos sea más rápida reduciéndola a una sola llamada mkdir, así como utilizando shell incorporado para pruebas y aritmética. Me gusta esto:

n=1
max=50
set -- # this sets $@ [the argv array] to an empty list.

while [ "$n" -le "$max" ]; do
    set -- "$@" "s$n" # this adds s$n to the end of $@
    n=$(( $n + 1 ));
done 

mkdir "$@"

Zsh, ksh93 o bash hacen esto mucho más fácil, pero debo señalar que esto no está integrado mkdiry puede no funcionar en otros shells. Para casos más grandes, también puede verse afectado por los límites en el número o el tamaño total de los argumentos que se pueden pasar a un comando.

mkdir s{1..50}
Aleatorio832
fuente
3
+1 ¡Esto es genial! Sin embargo, tengo que pensar en una cosa: n=$(( n + 1 ))habría sido tan estrictamente POSIX y no le costaría una subshell.
kojiro
@rahmu la [[palabra clave no es POSIX. (Sin mencionar que [ es una concha incorporada en muchas conchas modernas.)
kojiro
@kojiro: [[funciona en mi ksh88(que es anterior bash), así que supuse que era POSIX. No pude encontrar ninguna mención de ello en la especificación POSIX, así que creo que tienes razón. Gracias por la info!
rahmu
Pensé en agregar una versión usando la expansión aritmética, pero quería limitar "sh puro" a cosas que también hubieran funcionado en versiones anteriores a POSIX. Tampoco mencioné seq por la misma razón: si tienes seq probablemente tengas bash. El ejemplo de bucle también es bueno para omitir los límites de argumentos para un mayor número de directorios, lo que también significa que hay un lugar for i in {range}para los usuarios de shells avanzados.
Random832
La sugerencia zsh al final es increíble, ¡me ahorró mucho tiempo!
Jase
33
  • Uno

    for i in {1..50}; do
      mkdir s"$i"
    done
  • Dos

    mkdir s{1..50}

    Esta opción funciona en bash , zsh y ksh93

  • Tres

    mkdir $(printf "s%02i " $(seq 1 50))
Jhonathan
fuente
44
¿Por qué usarías uno sobre dos?
Kevin
77
es posible que desee hacer más $ique simplemente crear un directorio, por ejemplo mkdir s$i ; echo $i > s$i/$i. Además, One es un ejemplo simple y agradable de usar un bucle for en bash ... en un sitio como este, no es nada improbable que un usuario novato lo vea y piense "bien, no me di cuenta de que podría hacer eso "---> iluminación.
cas
1
@rahmu Es una característica que se encuentra en Bash / Zsh (probablemente también ksh93). No hay necesidad de votar abajo.
helpermethod
3
@rahmu: Creo que uno solo debería considerar si la respuesta de jhonathan soluciona el problema con el shell de OP (bash), no necesariamente con otros.
Francesco Turco
44
@Kevin, aunque no es probable que sea un problema para cincuenta, si tiene quinientos directorios para hacer, podría preocuparse por los límites de los argumentos.
Random832
10

Muchas respuestas complicadas aquí, pero bash lo hace realmente fácil. Claro, la solución POSIX pura funciona, pero ¿por qué no aprovechar el bashshell que está utilizando, de todos modos? Puede hacerlo fácilmente con la expansión de llaves :

% mkdir -v s{1..10} && ls -1d s{1..10}                                   (09-24 17:37)
mkdir: created directory `s1'
mkdir: created directory `s2'
mkdir: created directory `s3'
mkdir: created directory `s4'
mkdir: created directory `s5'
mkdir: created directory `s6'
mkdir: created directory `s7'
mkdir: created directory `s8'
mkdir: created directory `s9'
mkdir: created directory `s10'
s1
s10
s2
s3
s4
s5
s6
s7
s8
s9
sombreador
fuente
5

mkdir $(seq --format 's%.0f' 1 50)

o si desea números con relleno de cero (lo que sería mejor para ordenar):

mkdir $(seq --format 's%02.0f' 1 50)

o:

mkdir s$(seq -s ' s' -w 1 50) - tenga en cuenta la cadena 's' justo antes de la $() , sin ella el primer directorio creado será solo '01' en lugar de 's01'

y finalmente: mkdir $(printf "s%02i " $(seq 1 50))

seq es de GNU Coreutils

curiosamente, seq --formatu -fopción solo permite los tipos dobles de coma flotante de printf (como f y g. también un extraño formato hexadecimal de coma flotante para el que nunca he encontrado ningún uso). No tengo ni idea de porqué. Sería bueno si también admitiera otros printf(3)tipos numéricos como entero (d, i), octal (o, U) o hexadecimal (x, X).

De todos modos, un formato doble con precisión decimal 0 como %.0f o %02.0festá lo suficientemente cerca de un entero para este propósito.

$ seq --ayuda
Uso: seq [OPCIÓN] ... ÚLTIMO
  o: seq [OPCIÓN] ... PRIMERO ÚLTIMO
  o: seq [OPCIÓN] ... PRIMER INCREMENTO ÚLTIMO
Imprima números de PRIMERO a ÚLTIMO, en pasos de INCREMENTO.

  -f, --format = FORMAT utiliza el formato printf de coma flotante FORMAT
  -s, --separator = STRING usa STRING para separar números (predeterminado: \ n)
  -w, --equal-width iguala el ancho rellenando con ceros a la izquierda
      - ayuda a mostrar esta ayuda y salir
      - versión de salida de información de versión y salida

Si se omite FIRST o INCREMENT, el valor predeterminado es 1. Es decir, un
el INCREMENTO omitido es 1 incluso cuando LAST es menor que FIRST.
PRIMERO, INCREMENTO y ÚLTIMO se interpretan como valores de coma flotante.
El INCREMENTO suele ser positivo si FIRST es menor que el LAST, y
El INCREMENTO generalmente es negativo si PRIMERO es mayor que ÚLTIMO.
FORMAT debe ser adecuado para imprimir un argumento de tipo 'double';
su valor predeterminado es% .PRECf si FIRST, INCREMENT y LAST son puntos fijos
números decimales con la máxima precisión PREC, y hasta% g en caso contrario.

Ver también: http://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html

cas
fuente
{1,50}o {01,50}(para relleno cero) es mucho más fácil y más comprensible.
Kevin
1
cierto ... si estás usando bash en lugar de sh. Es por eso que voté por la respuesta de @ Random832. Es una buena respuesta. usar seq también es una respuesta útil.
cas
4

Para ser diferente, aquí hay una solución POSIX sh que utiliza la recursividad:

makedirs() {
  [ "$1" -gt 0 ] || return
  mkdir "s$1"
  makedirs $(( $1 - 1 ))
}
$ makedirs 9
$ ls
s1  s2  s3  s4  s5  s6  s7  s8  s9
kojiro
fuente