Busca e move arquivos renomeando-os conforme a máscara

Publicado por Marcio Gil (última atualização em 15/09/2010)

[ Hits: 8.098 ]

Download 4741.rename

Download 1283889791.rename (versão 2)




Busca e move arquivos renomeando-os conforme a máscara

Uso:
  rename [opções] [caminho1/]máscara1 [caminho2/]máscara2
  rename [opções] --sed 'expr' [caminho/]máscara

Opções:
  --test    Não move/renomeia, apenas mostra o que será feito
  --cmd mv  Determina o comando para mover/renomear e zera as opções
  --sed exp Determina uma expressão "sed" no lugar de "máscara2"
  --recursive,
  -R,-r     Buscar arquivos no diretório e subdiretórios de origem
  -*        Outras opções são repassadas ao comando "mv" (-vb implícito)

Exemplos:
  rename \*.*~ \*.bak
  rename '*.*~' '*.bak'
  rename "*.*~" "*.bak"
  rename --sed 's/\..*~$/.bak/' \*.*~

  



Versões atualizadas deste script

Versão 2 - Enviado por Marcio Gil em 07/09/2010

Changelog: - Sistema de contrução de expressão mehorado
- Agora suporta os coringas *, ? e [...] na máscara de origem
- e os coringas *, ? e #n na máscara de destino
- Regras mais claras para a correspondência das máscaras
- Opção -icase para ignorar maiúsculas ou minúsculas no nome dos arquivos

Download 1283889791.rename


Esconder código-fonte

#!/bin/bash
#
# rename: Busca e move arquivos renomeando-os conforme a máscara
# Criado por: Marcio Gil Maldonado
#

cmd=`basename $0`

if [ "$1" == "--help" ] ; then
  echo "Busca e move arquivos renomeando-os conforme a máscara"
  echo
  echo "Uso:"
  echo "  $cmd [opções] [caminho1/]máscara1 [caminho2/]máscara2"
  echo "  $cmd [opções] --sed 'expr' [caminho/]máscara"
  echo
  echo "Opções:"
  echo "  --test    Não move/renomeia, apenas mostra o que será feito"
  echo "  --cmd mv  Determina o comando para mover/renomear e zera as opções"
  echo "  --sed exp Determina uma expressão \"sed\" no lugar de \"máscara2\""
  echo "  --recursive,"
  echo "  -R,-r     Buscar arquivos no diretório e subdiretórios de origem"
  echo "  -*        Outras opções são repassadas ao comando \"mv\" (-vb implícito)"
  echo
  echo "Exemplos:"
  echo "  $cmd \\*.*~ \\*.bak"
  echo "  $cmd '*.*~' '*.bak'"
  echo "  $cmd \"*.*~\" \"*.bak\""
  echo "  $cmd --sed 's/\..*~$/.bak/' \\*.*~"
  echo
  exit 0
fi

# Tratamento dos parâmetros

istest="0"
mvcmd="mv"
mvopt="-vb"
maxdepth_o="-maxdepth"
maxdepth_n="1"
sedexpr=""
oldname=""
newname=""

while [ $# -gt 0 ] ; do
  case "$1" in
    --test) istest="1" ;;
    --cmd)  mvcmd="$2" ; mvopt="" ; shift ;;
    --sed)  sedexpr="$2" ; shift ;;
    --recursive|-R|-r) maxdepth_o="" ; maxdepth_n="" ;;
    -*)     mvopt="$mvopt $1" ;;
    *)
    if [ -z "$oldname" ] ; then
      oldname="$1"
    elif [ -z "$newname" -a -z "$sedexpr" ] ; then
      newname="$1"
    else
      echo "$cmd: Excesso de parâmetros: $1" >&2
      echo "$cmd: Execute '$cmd --help' para mais informações." >&2
      exit 1
    fi
  esac
  shift
done

if [ -z "$oldname" ] ; then
  echo "$cmd: Máscara de origem não informado" >&2
  echo "$cmd: Execute '$cmd --help' para mais informações." >&2
  exit 1
fi
if [ -z "$newname" -a -z "$sedexpr" ] ; then
  echo "$cmd: Máscara de destino não informado" >&2
  echo "$cmd: Execute '$cmd --help' para mais informações." >&2
  exit 1
fi

patt=`basename "$oldname"`
if [ "$oldname" == "$patt" ] ; then
  mvdir="."
else
  mvdir=`dirname "$oldname"`
  oldname="$patt"
fi

patt=`basename "$newname"`
if [ "$newname" == "$patt" ] ; then
  mvdst="$mvdir"
else
  mvdst=`dirname "$newname"`
  newname="$patt"
fi

# Montagem da expressão 'sed'

if [ -z "$sedexpr" ] ; then
  oldpatt=`echo -n "$oldname" | sed -e 's/[^*?]*\([*?]\?\)[^*?]*/\1/g'`
  newpatt=`echo -n "$newname" | sed -e 's/[^*?]*\([*?]\?\)[^*?]*/\1/g'`

  if [ "$newpatt" != "$oldpatt" ] ; then
    op=`echo -n "$oldpatt" | wc -m`
    np=`echo -n "$newpatt" | wc -m`
    if (( $op < $np || $np == 0 )) ; then
      echo "$cmd: As máscaras de origem e destino são incompatíveis" >&2
      echo "$cmd: Execute '$cmd --help' para mais informações." >&2
      exit 1
    fi
  fi

  oldpatt=`echo -n "$oldname" | sed -e 's/[.]/\\\\./g;s#/#\\\\/#g' \
                                    -e 's/[*]/\\\\(.*\\\\)/g;s/\([?]\)/\\\\(.\\\\)/g'`
  newpatt=`echo -n "$newname" | sed -e 's/[.]/\\./g;s#/#\\/#g'`

  np="1"
  while : ; do
    patt=`echo -n "$newpatt" | sed -e "s/[*?]/\\\\\\\\$np/"`
    if [ "$newpatt" == "$patt" ] ; then
      break
    fi
    newpatt="$patt"
    np=$(( $np + 1 ))
  done

  sedexpr="s/$oldpatt/$newpatt/"
fi

# Efetua/exibe as operações

if (( $istest )) ; then
  echo find "\"$mvdir\"" $maxdepth_o $maxdepth_n -name "\"$oldname\""
fi

IFS=$'\n'
for f in `find "$mvdir" $maxdepth_o $maxdepth_n -name "$oldname"` ; do
  g=`echo -n "$f" | sed "s#^$mvdir##" | sed "$sedexpr"`
  if (( $istest )) ; then
    echo "$mvcmd" $mvopt "\"$f\"" "\"$mvdst$g\""
  else
    "$mvcmd" $mvopt "$f" "$mvdst$g"
  fi
done

# End of rename

Scripts recomendados

Configurando JDK no PATH no Linux (qualquer distro)

Linux Mint 20 Pós Instalação

Album virtual para WEB

Instalação do LAMP no Linux Ubuntu

Script para desconexão em horário determinado


  

Comentários
[1] Comentário enviado por Daemonio em 01/09/2010 - 12:28h

Bacana, Márcio.
Lembro desse script na lista Shell-Script do Júlio Cezar. Era você mesmo lá, né?

Bem vindo ao vol!!!

t+

[2] Comentário enviado por marciomgil em 01/09/2010 - 13:26h

[Pois é, era eu mesmo. Mas digamos que não me dei bem na ditadura...]

Quanto ao script, em geral funciona bem, fiz ele uma década passada para funcionar como o comando REN do DOS, mas um dia desses teve um caso em que o script não fez o que era esperado. Não tive tempo de corrigir, mas farei isso para atualizar aqui no VivaOLinux.

[3] Comentário enviado por marciomgil em 07/09/2010 - 17:20h

O caso de que falei foi uma tentativa de remover o prefixo "Cópia de " de alguns arquivos. Como o meu terminal não aceitava acento, eu, sem pensar, tentei assim:

rename "C?pia de *" "*"

Mas o asterisco foi substituído por "\1" que correspondia ao "?", ou seja, todos os arquivos foram renomeados para "ó". Para funcionar eu tive de mudar para:

rename "C\363pia de *" "*"

Porém, como não quero ficar consultando a tabela ASCII sempre que tiver problemas com acentos, criei uma nova versão que aceita o coringa "#n" em "máscara2", além de forçar a correspondência do coringa "?" em "máscara1" com outro coringa "?" em "máscara2". Então agora eu posso fazer o que queria de duas formas:

rename "C?pia de *" "*"
rename "C?pia de *" "#2"

A nova versão está em espera.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts