Como posso excluir arquivos numerados em um determinado intervalo?

10

Eu tenho folderA que tem alguns arquivos com uma seqüência numérica começando com a_000000 . O que eu quero fazer é excluir os arquivos a partir de um número específico: digamos a_000750 até o final dos arquivos neste folderA . Alguém poderia por favor aconselhar como fazer isso usando o script de shell?

    
por Tak 27.09.2014 / 16:22

3 respostas

22

Supondo que você saiba ou consiga adivinhar o final do intervalo, você pode usar expansões de chaves :

rm a_{000750..000850}

O texto acima excluirá os 101 arquivos entre a_000750 e a_000850 inclusive (e reclamará sobre nomes de arquivos que se referem a arquivos não existentes). Se você tiver muitos arquivos para isso, use find :

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

Aqui, o find simplesmente lista todos os arquivos correspondentes a a_* . A lista é passada para um loop while , em que cada nome de arquivo é lido na variável $file . Em seguida, usando os recursos de do bash, se a parte numérica (localizar, imprime arquivos como ./file , então ${file#./a_} imprime apenas o número) é 000750 ou maior, o arquivo é excluído. O -v está lá apenas para que você possa ver quais arquivos foram removidos.

Observe que o acima assume nomes de arquivos sãos. Se seus nomes podem ter espaços, novas linhas ou outros caracteres estranhos, use isso:

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done
    
por terdon 27.09.2014 / 17:00
3

Você poderia fazer algo assim:

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo ' "removing: " {} \;

Ou:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

O primeiro método assume um prefixo fixo, retira-o e verifica o valor.

O segundo método assume um sufixo de comprimento fixo (e um prefixo fixo comum) e se baseia nesse fato; e que, enquanto 201 vem antes de 31 em lexicograficamente, não é antes de 031 .

Teste isso com o comando echo e, assim que tiver certeza de que ele lista os arquivos corretos, use rm .

    
por muru 27.09.2014 / 16:33
0

Solução de shell POSIX

A primeira solução da terdon depende da expansão de chaves, que é uma propriedade de bash e ksh , no entanto não pode ser usado no shell padrão /bin/sh , que no Ubuntu é linkado por link simbólico para /bin/dash .

Nos casos em que você precisa confiar em /bin/sh para a portabilidade de seus scripts, geralmente há duas maneiras de abordar isso. Um seria via globbing. Apenas cd folderA e a partir daí, execute rm a_* . A outra maneira, seria implementar uma alternativa de loop de estilo C usando while <CONDITION>;do ...done na linguagem shell e formatar os números com printf :

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

Observe que aqui eu uso echo . Substitua echo "$filename" por rm ./"$filename" ou rm -- "$filename" quando estiver pronto para excluir os arquivos. Observe também que isso deve ser feito quando você já tiver cd ed no diretório desejado.

(ab) usando o awk

Awk, sendo uma linguagem legal semelhante ao C, pode nos ajudar de duas maneiras: (1) podemos gerar nomes de arquivos com loop e formatá-los via sprintf function, e (2) deletar os arquivos via system() command , que irá passar o nosso nome de arquivo gerado e o comando rm para /bin/sh :

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

Perl

Continuando com a ideia de abordagem portátil onde "geramos" nomes de arquivos, podemos fazer o mesmo em Perl:

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'
    
por Sergiy Kolodyazhnyy 18.11.2017 / 19:17