Criando vários diretórios usando o mkdir

13

Eu gostaria de criar muitos diretórios usando mkdir. Cada nome de diretório consistirá em um prefixo (uma sequência) e um índice (um número inteiro). Suponha que eu gostaria que o prefixo fosse "s" e os índices variassem de 1 a 50. Isso significa que eu gostaria de criar diretórios intitulados:

s1,, s2... s49,,s50

Existe uma maneira de fazer isso automaticamente usando mkdir? Obrigado pelo seu tempo.

Andrew
fonte
2
Qual shell você está usando?
Francesco Turco
@FrancescoTurco Estou usando bash. Obrigado pelo seu tempo!
Andrew
3
FYI, acho que é muito mais útil para usar índices de largura fixa, como: s01, s02, ..., s49, s50. Se eu usei índices de largura fixa, /bin/lsquase sempre produz a ordem que desejo.
Rob

Respostas:

31

Você pode fazer isso com um script de shell.

Sh puro - isso funcionará mesmo em cascas de bourne pré-POSIX:

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

Se você deseja criar um número alto de diretórios, pode tornar o script mais rápido, reduzindo-o a uma única chamada mkdire usando os recursos internos do shell para testes e aritmética. Como isso:

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 ou bash tornam isso muito mais fácil, mas devo ressaltar que isso não está embutido mkdire pode não funcionar em outros shells. Para casos maiores, também pode ser afetado por limites no número ou tamanho total de argumentos que podem ser passados ​​para um comando.

mkdir s{1..50}
Random832
fonte
3
+1 Isso é ótimo! Mas preciso esclarecer uma coisa: n=$(( n + 1 ))teria sido tão estritamente POSIX e não lhe custaria um subshell.
kojiro
@rahmu a [[palavra-chave não é POSIX. (Para não mencionar que [ é um builtin shell em muitos shells modernos.)
kojiro
@ kojiro: [[funciona no meu ksh88(que é anterior bash), então eu assumi que era POSIX. Não encontrei nenhuma menção a isso na especificação POSIX, portanto acredito que você está certo. Obrigado pela informação!
rahmu
Pensei em adicionar uma versão usando expansão aritmética, mas queria limitar "sh puro" a coisas que funcionariam também nas versões pré-POSIX. Também não mencionei seq pelo mesmo motivo - se você tiver seq, provavelmente terá o bash. O exemplo de loop também é bom para ignorar os limites de argumentos para um número maior de diretórios, o que também significa que há um lugar for i in {range}para os usuários de shells avançados.
usar o seguinte código
A dica do zsh no final é incrível, me salvou muito tempo!
Jase
33
  • 1

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

    mkdir s{1..50}

    Esta opção funciona no bash , zsh e ksh93

  • Três

    mkdir $(printf "s%02i " $(seq 1 50))
Jhonathan
fonte
4
Por que você usaria um sobre dois?
Kevin
7
você pode querer fazer mais do $ique apenas criar um diretório, por exemplo mkdir s$i ; echo $i > s$i/$i. Além disso, One é um exemplo simples e agradável de usar um loop for no bash ... em um site como este, não é improvável que um usuário iniciante o veja e pense "bom, eu não sabia que você poderia fazer isso" "---> iluminação.
cas
1
@rahmu É um recurso encontrado no Bash / Zsh (provavelmente também no ksh93). Não há necessidade de voto negativo.
precisa saber é o seguinte
3
@rahmu: Eu acho que só devemos considerar se a resposta de jhonathan resolve o problema com o shell do OP (bash), não necessariamente com os outros.
Francesco Turco
4
@ Kevin, embora não seja provável que seja um problema para cinquenta, se você tiver quinhentos diretórios para fazer você se preocupar com os limites de argumentos.
usar o seguinte comando
10

Muitas respostas complicadas aqui, mas o bash facilita muito. Claro, a solução POSIX pura funciona, mas por que não tirar proveito do bashshell que você está usando? Você pode fazer isso facilmente com a expansão de chaves :

% 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
laebshade
fonte
5

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

ou se você quiser números preenchidos com zero (o que seria melhor para a classificação):

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

ou:

mkdir s$(seq -s ' s' -w 1 50)- observe a string 's' logo antes de $(), sem ela o primeiro diretório criado será apenas '01' em vez de 's01'

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

seq é do GNU Coreutils

estranhamente, seq's --formatou -foption apenas permitem tipos duplos de ponto flutuante do printf (como f e g. também um formato hexadecimal de ponto flutuante estranho que eu nunca encontrei utilidade). Eu não tenho ideia do porquê. Seria bom se ele também suportasse outros printf(3)tipos numéricos como número inteiro (d, i), octal (o, U) ou hex (x, X).

De qualquer forma, um formato duplo com precisão decimal 0 como %.0fou %02.0fé próximo o suficiente de um número inteiro para essa finalidade.

$ seq --help
Uso: seq [OPTION] ... ÚLTIMO
  ou: seq [OPÇÃO] ... PRIMEIRO ÚLTIMO
  ou: seq [OPÇÃO] ... PRIMEIRO INCREMENTO ÚLTIMO
Imprima números de PRIMEIRO a ÚLTIMO, nas etapas de INCREMENTO.

  -f, --format = FORMAT usa FORMAT de ponto flutuante no estilo printf
  -s, --separator = STRING usa STRING para separar números (padrão: \ n)
  -w, --equal-width iguala a largura preenchendo com zeros à esquerda
      --help exibe esta ajuda e sai
      --version informações da versão de saída e saída

Se PRIMEIRO ou INCREMENTO for omitido, o padrão será 1. Isto é, um
omitido INCREMENT, o padrão é 1, mesmo quando ÚLTIMO for menor que o PRIMEIRO.
PRIMEIRO, INCREMENTO e ÚLTIMO são interpretados como valores de ponto flutuante.
O INCREMENTO é geralmente positivo se o PRIMEIRO for menor que o ÚLTIMO, e
O aumento é geralmente negativo se o PRIMEIRO for maior que o ÚLTIMO.
FORMAT deve ser adequado para imprimir um argumento do tipo `double ';
o padrão é% .PRECf se PRIMEIRO, INCREMENTO e ÚLTIMO forem todos ponto fixo
números decimais com precisão máxima PREC, e para% g caso contrário.

Veja também: http://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html

cas
fonte
{1,50} ou {01,50} (para preenchimento zero) é muito mais fácil e compreensível.
Kevin
1
verdadeiro ... se você estiver usando o bash, em vez de sh. foi por isso que votei na resposta da @ Random832. é uma boa resposta. usar seq também é uma resposta útil.
cas
4

Apenas para ser diferente, aqui está uma solução POSIX sh que usa recursão:

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