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

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

[ Hits: 7.810 ]

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

Multimidia com Zenity

Firewall Linuxman

MRTG Start | Stop | Status | Restart

Teste compatativo entre discos e/ou partições

Implementando um simples manipulador de eventos de teclado


  

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