Eu tenho uma lista numerada de arquivos como este:
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
03_file_name.log
03_file_name.txt
04_file_name.log
04_file_name.txt
05_file_name.log
05_file_name.txt
Eu quero inserir novos arquivos para todos 03*
e 04*
arquivos. Então, a partir do número 03
de wards, todos os arquivos precisam ser movidos/renomeados com seu número inicial aumentado em 2, então a lista ficaria assim:
01_file_name.log
01_file_name.txt
02_file_name.log
02_file_name.txt
05_file_name.log
05_file_name.txt
06_file_name.log
06_file_name.txt
07_file_name.log
07_file_name.txt
Estou pensando em algo como:
bash script.sh 03 02
while 03
on $1
é o número do nome do arquivo para começar e 02
no $2
número a ser adicionado. Tentei fazer isso com um aninhado for-loop
, mas tive que desistir da combinação de usar um contador ((++))
para fazer o loop executar apenas os arquivos do número fornecido nas alas.
Isso faz o que você quer. Uma coisa: só funciona em BASH, eu acho.
MAXDIGITS
é opcional, eu coloco lá caso você precise trabalhar com três dígitos ou mais. Se você não usá-lo, exclua as linhas correspondentes.Para usá-lo:
Se você tiver outros arquivos no mesmo diretório que não estejam de acordo com a mesma sintaxe (prefix_filename.{txt,log}), você deve filtrá-los. Além disso, usei o "_" para separar o prefixo do nome do arquivo, portanto, se você alterar isso, precisará corrigir o código.
Para o que vale a pena, aqui está um
bash
one-liner que envolve duas substituições de processos e um procedimento muito simplesawk
:Explicação:
O forro acima é lido, ou pelo menos "compreendido", da direita para a esquerda.
ls -r -1 *_file_name.{log,txt}
lista todos os arquivos a serem processados em ordem inversa, no formato de uma coluna.Observe que, se os prefixos de arquivo (simbolizados por
*
) incluírem caracteres não numéricos, você poderá obter resultados imprevistos/indesejados. Para evitar isso, filtre os arquivos a serem processados nesta fase.<(...)
substituição do processo. Ele permite que a saída do resultado anterior seja referenciada usando um descritor de arquivo, ou seja, um arquivo temporário especial chamado pipe nomeado . Para detalhes emiteman bash
no terminal.awk
roteiro:BEGIN{FS="_"}
antes de começar a processar os registros, defina o separador de campo do registro para "_" (1º bloco do awk)awk
condicional do 2º bloco do$1>2
: processa apenas os registros cujo prefixo do nome do arquivo é estritamente maior que 2prefix=$1+2
define a variável interna "prefixo" do awk. Torná-lo numericamente igual ao prefixo$1
+ 2printf("my_format",var1,var2,...)
para imprimir comandos formatados, separados por uma nova linha. Observe que a formatação envolve%0.2d
, ou seja, imprimirawk
a variável "prefixo" como um número de dois dígitos com preenchimento 0 sempre que necessário. A saída é:mv -f 05_file_name.log 07_file_name.log
mv -f 05_file_name.txt 07_file_name.txt
mv -f 04_file_name.log 06_file_name.log
mv -f 04_file_name.txt 06_file_name.txt
mv -f 03_file_name.log 05_file_name.log
mv -f 03_file_name.txt 05_file_name.txt
mv -f ...
comandos.Se você se pergunta por que usar repetidamente a substituição do processo de entrada ou saída (não uma coisa POSIX!)
bash
é vantajoso, veja isso , por exemplo.Nota final:
Incluir parâmetros de tempo de execução no one-liner acima e encapsulá-lo em um script de shell executável é fácil, começando com a definição
VAR1
eVAR2
a atribuição aoawk
procedimento do :E em um script executável,
script.sh
:onde
VAR1
eVAR2
tem o significado definido no OP. Se você precisar usar esse script no ambiente de produção, recomendo adicionar várias verificações e proteções contra falhas para garantir que os valores de seus arquivos de entrada e variáveis sejam os esperados em todos os momentos.O script do @MarceloCastro é bom, embora seja baseado em um
for
loop, que costumo evitar sempre que possível.for
loops tendem a ser lentos, algo que você pode notar se processar uma grande quantidade de arquivos.Eu fiz este script que se encaixaria no seu objetivo.
Com
zsh
:Em seguida, remova
-n
(para execução a seco) para realmente fazê-lo.zmv pattern replacement
:zmv
é uma função autocarregável que aproveita os poderosos zsh glob e operadores de expansão para renomear arquivos complexos.<x-y>
corresponde ao número decimal x a y.(#q...)
qualificador globnOn
:n
numericamente rdero
(invertido com O maiúsculo) porn
ame. Então05...
virá antes04...
conforme necessário aqui já que estamos incrementando os números.${(l:n::padding:)expansion}
:l
eft pad a expansão para comprimento n usando padding . Então, com${(l:2::0:)}
, pad esquerdo para comprimento 2 com 0s.$(($1+2))
, o primeiro grupo capturado incrementado em 2.$2
: o segundo grupo de captura: o que vem depois do número inicial.