Renomear vários arquivos para diminuir o número no nome do arquivo?

Renomear vários arquivos para diminuir o número no nome do arquivo?

Nomeei incorretamente arquivos que não estão sincronizados por -1. O problema é que preciso renomear milhares deles.

  • DBGC180_805754
  • DBGC180_805755
  • DBGC180_805756

para

  • DBGC180_805753
  • DBGC180_805754
  • DBGC180_805755

Eu preferiria usar scripts bash ou um comando unix.

Responder1

Você consegue fazer isso:

# {smallestfilenum..largestfilenum}

for i in {805754..999999}; do 
   mv "DBGC180_$i" "DBGC180_$(($i-1))";
done

Experimente com um número pequeno (digamos 805754..805758) para ter certeza de que funciona conforme o esperado. Esteja ciente de que se já existir um arquivo com o novo nome, ele será sobrescrito.

Responder2

  1. Mova os arquivos a serem renomeados para um subdiretório (sem alterar seus nomes).
  2. Renomeie os arquivos do subdiretório para o diretório original.

Há dois motivos pelos quais recomendo a etapa 1, mesmo que seja possível passar sem ela:

  • Se o comando for interrompido, você poderá continuar de onde parou, pois fica imediatamente óbvio quais arquivos já foram renomeados e quais não foram.
  • Você não precisa se preocupar em renomear na ordem errada e substituir um dos arquivos existentes.

Snippet de shell não testado (baseando-se no fato de que o número a ser decrementado nunca possui zeros à esquerda):

mkdir to_decrement
for x in DBGC180_80575[4-9] DBGC180_8057[6-9]? DBGC180_805[8-9]?? DBGC180_80[6-9]??? DBGC180_8[1-9]???? DBGC180_9?????; do
  mv "$x" to_decrement/
done
cd to_decrement
for x in *; do
  number="${x##*_}"
  mv -i -- "$x" "../${x%_*}_$((number-1))"
done
cd ..
rmdir to_decrement

Comzsh, você pode tornar isso muito mais simples, graças ao seuglob de intervalo numérico, isso éconstruídas emmvque evita atingir limites de comprimento de linha de comando e seufunção de renomeação em massa baseada em padrão. Em zsh:

autoload -U zmv
zmodload -m -F zsh/files b:zf_\*
mkdir to_decrement
zf_mv DBGC180_<805754-> to_decrement/
zmv 'to_decrement/(*)_(*)' '${1}_$(($2-1))'
rmdir to_decrement

Responder3

Então, você deseja renomear DBGC180_805754para DBGC180_805753, ...55para ...54e assim por diante. Esse é o problema que abordarei.

Primeiro, coloque esse script em algum lugar do seu PATHarquivo waltinator.

#!/bin/bash
#step through the parameters 
while [[ -n "$1" ]] ; do
    oldname="$1"
    # shift the arguments left
    shift;
    # strip off the fixed part of the old name
    oldnum=${oldname##DBGC180_}
    # decrement the number (this is what was wanted, right?)
    newnum=$(( $oldnum - 1 ))
    # build the new, improved filename
    newname="DBGC180_$newnum"
    if [[ -f "$newname" ]] ; then
        printf "Cannot rename $oldname to $newname, $newname exists.\n" >&2
        exit 1
    fi
    mv --no-clobber "$oldname" "$newname"
done
exit 0

Para a próxima etapa, suponha que o script esteja in $HOME/bin/waltinatore você tenha does chmod +x $HOME/bin/waltinator.

find . -type f -name 'BDGC180_[0-9][0-9][0-9][0-9][0-9][0-9]` -print | \
    sort | \
    xargs $HOME/bin/waltinator

Os findarquivos encontrados (sem nenhuma ordem específica), cujos nomes correspondem ao padrão shell glob " BDGC180_seguido por 6 dígitos ( [0-9]). Como queremos uma lista classificada (seria uma falha renomear ...97antes ...96de renomear ...96), executamos a saída de findthrough sort. Em seguida, usamos xargsa lista (classificada) de nomes de arquivos e construímos um comando para passar a lista (classificada) de nomes de arquivos $HOME/bin/waltinatorpara Read man xargsse você precisar encurtar a lista de argumentos.

A propósito, leia:

for page in bash mv find sort xargs ; do
    man "$page"
done   

Responder4

Use renamepara substituir cada número por ele mesmo menos 1.

$ rename -v 's/\d{6}/sprintf("%06",($&-1))/e'    

Notas

  • renameusa expressões Perl para renomear nomes de arquivos.
  • sespecifica que renamesubstituirá alguns ou todos os nomes de arquivos que correspondem ao padrão de expressão regular.
  • As expressões de substituição Perl são estruturadas como tal.
    • s/PATTERN/REPLACEMENT/MODIFIER
  • \d{6}é o padrão que renameirá procurar e substituir. São 6 dígitos decimais.
  • $é a variável que armazena a substring correspondente \d{6}(neste caso, a "substring" é um int).
  • sprintf("%06",($&-1))recupera o valor armazenado em $, decrementa-o e retorna esse valor como substituto. O %06existe para lidar com zeros à esquerda.
  • eespecificado que renameavalia a substituição como se fosse uma instrução Perl e usa seu valor de retorno como o texto de substituição.
  • -vfaz renameecoar o que está fazendo.

Se você quiser ser mais seguro, use o sinalizador -npara renameinformar apenas o que faria em vez de fazê-lo.

Isso parece funcionar apenas para diminuir, portanto, lide com isso com cuidado.

informação relacionada