Pergunta

Qual é a melhor maneira, usando Bash, de renomear arquivos no formato:

(foo1, foo2, ..., foo1300, ..., fooN)

Com nomes de arquivos preenchidos com zeros:

(foo00001, foo00002, ..., foo01300, ..., fooN)
Foi útil?

Solução

Em caso N não é fixo a priori:

 for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done

Outras dicas

Não é puro bash, mas é muito mais fácil com o rename comando:

rename 's/\d+/sprintf("%05d",$&)/e' foo*

Tive um caso mais complexo em que os nomes dos arquivos tinham um postfix e também um prefixo.Também precisei realizar uma subtração do número do nome do arquivo.

Por exemplo, eu queria foo56.png tornar-se foo00000055.png.

Espero que isso ajude se você estiver fazendo algo mais complexo.

#!/bin/bash

prefix="foo"
postfix=".png"
targetDir="../newframes"
paddingLength=8

for file in ${prefix}[0-9]*${postfix}; do
  # strip the prefix off the file name
  postfile=${file#$prefix}
  # strip the postfix off the file name
  number=${postfile%$postfix}
  # subtract 1 from the resulting number
  i=$((number-1))
  # copy to a new name with padded zeros in a new folder
  cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)
done

O comando oneline que eu uso é este:

ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done

PADRÃO pode ser, por exemplo:

  • renomear com contador de incremento: %04d.${f#*.} (manter a extensão do arquivo original)
  • renomear com contador de incremento com prefixo: photo_%04d.${f#*.} (manter extensão original)
  • renomeie com contador de incrementos e altere a extensão para jpg: %04d.jpg
  • renomear com contador de incremento com prefixo e nome de base do arquivo: photo_$(basename $f .${f#*.})_%04d.${f#*.}
  • ...

Você pode filtrar o arquivo para renomear, por exemplo ls *.jpg | ...

Você tem disponível a variável f esse é o nome do arquivo e i esse é o contador.

Para sua pergunta o comando certo é:

ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done

Pure Bash, nenhum processo externo além de 'mv':

for file in foo*; do
  newnumber='00000'${file#foo}      # get number, pack with zeros
  newnumber=${newnumber:(-5)}       # the last five characters
  mv $file foo$newnumber            # rename
done

O seguinte fará isso:

for ((i=1; i<=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done

EDITAR: alterado para usar ((i=1,...)), obrigado Mweerden!

Aqui está uma solução rápida que assume um prefixo de comprimento fixo (seu "foo") e preenchimento de comprimento fixo.Se precisar de mais flexibilidade, talvez este seja pelo menos um ponto de partida útil.

#!/bin/bash

# some test data
files="foo1
foo2
foo100
foo200
foo9999"

for f in $files; do
    prefix=`echo "$f" | cut -c 1-3`        # chars 1-3 = "foo"
    number=`echo "$f" | cut -c 4-`         # chars 4-end = the number
    printf "%s%04d\n" "$prefix" "$number"
done

Minha solução substitui números, em todos os lugares de uma string

for f in * ; do
    number=`echo $f | sed 's/[^0-9]*//g'`
    padded=`printf "%04d" $number`
    echo $f | sed "s/${number}/${padded}/";
done

Você pode experimentá-lo facilmente, pois ele apenas imprime nomes de arquivos transformados (nenhuma operação do sistema de arquivos é executada).

Explicação:

Percorrendo a lista de arquivos

Uma volta: for f in * ; do ;done, lista todos os arquivos e passa cada nome de arquivo como $f variável para fazer o loop do corpo.

Pegando o número da string

Com echo $f | sed nós canalizamos variável $f para sed programa.

No comando sed 's/[^0-9]*//g', papel [^0-9]* com modificador ^ diz para corresponder ao oposto do dígito 0-9 (não um número) e, em seguida, removê-lo com substituição vazia //.Por que não apenas remover [a-z]?Porque o nome do arquivo pode conter pontos, traços, etc.Então, tiramos tudo, que não é um número e pegamos um número.

A seguir, atribuímos o resultado a number variável.Lembre-se de não colocar espaços na tarefa, como number = …, porque você obtém um comportamento diferente.

Atribuímos o resultado da execução de um comando à variável, envolvendo o comando com símbolos de crase `.

Preenchimento zero

Comando printf "%04d" $number altera o formato de um número para 4 dígitos e adiciona zeros se nosso número contiver menos de 4 dígitos.

Substituindo o número por um número preenchido com zeros

Nós usamos sed novamente com comando de substituição como s/substring/replacement/.Para interpretar nossas variáveis, usamos aspas duplas e substituímos nossas variáveis ​​desta forma ${number}.


O script acima apenas imprime nomes transformados, então, vamos fazer o trabalho real de renomeação:

for f in *.js ; do
    number=`echo $f | sed 's/[^0-9]*//g'`
    padded=`printf "%04d" $number`
    new_name=`echo $f | sed "s/${number}/${padded}/"`
    mv $f $new_name;
done

Espero que isso ajude alguém.

Passei várias horas para descobrir isso.

Para inserir números no teclado esquerdo em nomes de arquivos:

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz

$ for f in [0-9]*.[a-z]*; do tmp=`echo $f | awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10

Explicação

for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
  • observe os crases: `echo ... $2}\` (A barra invertida, \, imediatamente acima apenas divide essa linha em duas linhas para facilitar a leitura)
  • em um loop, encontre arquivos nomeados como números com extensões alfabéticas em minúsculas: [0-9]*.[a-z]*
  • ecoe esse nome de arquivo ($f) para passá-lo para awk
  • -F. : awk separador de campos, um ponto (.):se houver correspondência, separa os nomes dos arquivos como dois campos ($1 = número; $2 = extensão)
  • formato com printf:imprima o primeiro campo ($1, a parte do número) como 4 dígitos (%04d), imprima o período e imprima o segundo campo ($2:a extensão) como uma string (%s).Tudo isso é atribuído ao $tmp variável
  • por último, mova o arquivo de origem ($f) para o novo nome do arquivo ($tmp)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top