Respostas:
A rename
ferramenta que acompanha o Ubuntu é bastante interessante nesse tipo de coisa. Você pode incorporar pequenas expressões Perl assim:
rename -n 's/.+/our $i; sprintf("AS%d.txt", 1+$i++)/e' *
Isso apenas mostrará o que faria. Remova o -n
para torná-lo um exercício de fogo vivo.
Isso basicamente funciona definindo uma variável aproximada e incrementando-a a cada arquivo que acessamos. Se você tiver mais de 10 arquivos, sugiro usar algum preenchimento zero no arquivo sprintf
. O seguinte é bom até 999
:
rename -n 's/.+/our $i; sprintf("AS%03d.txt", 1+$i++)/e' *
... Mas isso é fácil de expandir.
Para melhorar a resposta do @ Oli , a versão 1.600 da rename
ferramenta de Aristóteles Pagaltzis, na verdade, possui um contador ,.$N
Então tudo que você precisa é,
rename 's/AS.*/AS$N/' *
Para instalar,
brew install rename
ou Faça o download do script/usr/local/bin/brew
ou /usr/bin
)rename
permite atribuir diretamente a $_
, o que é ideal para esse problema.Embora os argumentos de código que passam ao Perl rename
utilidade muitas vezes executar a correspondência e substituição (com s/
), e é totalmente aceitável para resolver este problema dessa forma , não há realmente nenhuma necessidade de que, em casos como este, onde você não está realmente examinar ou reutilizando o texto dos antigos nomes de arquivos. rename
permite escrever praticamente qualquer código Perl, e ele não precisa ser incorporado s/
/e
. Eu sugiro usar um comando como este:
rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' *
Ou, se você desejar cortar alguns caracteres:
rename -n '$_ = sprintf "AS%02d.txt", ++our$i' *
(Pode ser ainda mais curto, mas não sem sacrificar a clareza.)
Ambos os comandos fazem a mesma coisa. Cada um mostra quais operações de renomeação seriam realizadas. Depois de experimentar e ficar satisfeito com os resultados, execute-o novamente sem a -n
opção Como está escrito, isto produziria os nomes de arquivos AS01.txt
, AS02.txt
, ..., AS10.txt
, AS11.txt
e assim por diante. Você pode modificá-los conforme necessário e depois remover apenas -n
quando gostar do que vê.
Se você deseja preencher uma largura maior que 2, substitua 2
por um número maior. Por exemplo, se por algum motivo você quiser nomes de arquivos como AS00000000000001.txt
, substitua %02d
por %014d
. Se você não desejar preenchimento - mesmo que isso faça com que seus arquivos apareçam em ordem não numérica quando você os listar mais tarde! -, poderá substituí-lo %02d
por apenas %d
.
Como é que isso funciona? Seu shell se expande *
para uma lista de arquivos antes mesmo de executar o rename
comando. A lista é classificada lexicograficamente (isto é, alfabeticamente) de acordo com as configurações atuais de localidade. rename
recebe os nomes dos arquivos como argumentos da linha de comando e os processa na ordem em que estão listados. A expressão é ++$i
avaliada como um maior que o valor atual da variável $i
e também define a variável $i
para esse valor recém-incrementado. Esse valor é passado para sprintf
, que o formata e o coloca dentro de outro texto. Este texto é atribuído diretamente à variável especial $_
, que contém o nome do arquivo. Como os rename
arquivos de processos estão na ordem em que são passados como argumentos, eles são numerados de acordo.
Ambos declaram e incrementam uma variável de contador e usam sprintf
essencialmente da mesma maneira para incorporar o valor desse contador, preenchido à esquerda com zeros, no outro texto dos novos nomes de arquivos. (As informações em qualquer resposta sobre como almofada com zeros - e alterar a largura estofamento -. Mesmo se aplica igualmente a ambos) A razão que eles são tão semelhantes é que o método em que a resposta mais velho está realmente fazendo apenas isso 1 , mas com etapas extras que são úteis para muitos problemas, mas não são realmente necessárias para este.
Para comparação, veja como é o segundo comando dessa resposta se modificado para usar o estilo que usei aqui (e para preencher uma largura de 2, como fiz aqui, em vez de 3):
rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' *
A parte entre s/.+/
e /e
nesse comando agora é a mesma que a expressão que atribuo $_
(ou seja, o código no lado direito do =
operador) no primeiro comando nesta resposta.
s/
operador tenta corresponder o texto (nomes de arquivo dos quais o seu shell expandiu *
e passou como argumentos da linha de comando quando executado rename
) com uma expressão regular e executa a substituição. /
está sendo usado como um delimitador para separar as diferentes partes da s
expressão. A primeira parte,, .+
é a expressão regular; ele corresponde qualquer um caractere ( .
) , e fá-lo uma ou mais vezes ( +
) . Como os nomes de arquivos nunca estão vazios - eles sempre têm pelo menos um caractere - esta é uma maneira de corresponder a qualquer nome de arquivo 1 .our $i; sprintf "AS%02d.txt", ++$i
. Isso produz o novo nome do arquivo. Normalmente, usa-se s/
para produzir texto que seja (a) substituindo texto que corresponde apenas a parte do nome do arquivo ou (b) com base no texto correspondente de alguma forma (por exemplo, ele pode usar uma variável especial como $&
essa que se expande para o jogo). Nesse caso, porém, o texto correspondente não está sendo usado.our $i; sprintf "AS%02d.txt", ++$i
seria usado como um nome de arquivo, não executado como código. Mas o /e
sinalizador no final faz com que o texto seja tratado como código-fonte Perl e avaliado, e usa o valor produzido com isso (nesse caso, o valor de retorno da função interna do Perl sprintf
) como o novo nome do arquivo.Embora eu acho que o método que eu tenho mostrado aqui é uma abordagem mais clara e mais simples para este problema do que qualquer método que usa s/
com /e
, é bom estar ciente de que a técnica, porque é bem adequado para uma série de outros renomear problemas de arquivo onde todos ou parte dos nomes de arquivos originais é examinada e / ou mantida. Eu recomendo este post de Oli (que também escreveu essa resposta ), que inclui alguns exemplos.
Uma técnica, não é uma diferença no comportamento dos $_ =
comandos e os s/
/e
comandos. Na expressão regular .+
, não é exatamente verdade que .
corresponde a qualquer caractere, porque não corresponde a uma nova linha . Você provavelmente não deve usar nomes de arquivos com novas linhas, mas pode e, ocasionalmente, um arquivo é nomeado dessa maneira por acidente. Se você quiser, compare a saída com rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'
a de rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar'
. Para fazer .
corresponder uma nova linha, use a s
bandeira, que fica no final (com e
). Ou seja, escreva /se
no final em vez de /e
.
Suponha que os arquivos que você deseja renomear estejam ~/Adir
e esses sejam os únicos arquivos nesta pasta;
n=0
for f in $( ls ~/Adir | sort ) ; do
n=$(( n+1 ))
mv -n "$f" "AS${n}.txt"
done
Este script examinará cada arquivo ~/Adir
e renomeá-lo para AS1.txt, AS2.txt, ...
se o arquivo não existir (não haverá substituição). É por isso que você deve se certificar de que esses são os únicos arquivos presentes ~/Adir
. O sort
comando é apenas no caso de você desejar que os arquivos mantenham a ordem inicial.
rename
é nome do arquivo. Isso pode ser melhor, mas convém adicionar instruções de instalação para tornar essa resposta mais valiosa.