ti-enxame.com

Renomear arquivos e diretórios de forma recursiva no ubuntu/bash

Eu quero renomear todos os arquivos e diretórios que contêm o Word "especial" para "regular". Ele deve manter a diferenciação entre maiúsculas e minúsculas, portanto, "Especial" não se tornará "regular".

Como posso fazer isso em bash recursivamente? 

53
Tom

Tente fazer isso (requer bash --version> = 4):

shopt -s globstar
rename -n 's/special/regular/' **

Remova a opção -n quando seus testes estiverem OK

warning Existem outras ferramentas com o mesmo nome que podem ou não ser capazes de fazer isso, então seja cuidadoso.

Se você executar o seguinte comando (GNU)

$ file "$(readlink -f "$(type -p rename)")"

e você tem um resultado como 

.../rename: Perl script, ASCII text executable

e não contendo:

ELF

então esta parece ser a ferramenta certa =)

Se não, para torná-lo o padrão (geralmente já o caso) em Debian e derivado como Ubuntu:

$ Sudo update-alternatives --set rename /path/to/rename

(substitua /path/to/rename pelo caminho do seu comando Perl's rename.


Se você não tiver este comando, procure em seu gerenciador de pacotes para instalá-lo ou faça-o manualmente


Por último, mas não menos importante, esta ferramenta foi originalmente escrita por Larry Wall, o pai do Perl.

68
Gilles Quenot

Uma solução usando find:

Para renomear apenas files:

find /your/target/path/ -type f -exec rename 's/special/regular/' '{}' \;

Para renomear apenas diretórios:

find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \+

Para renomear ambos files e diretórios:

find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
88
speakr

Se você não se importar de instalar outra ferramenta, então você pode usar rnm :

rnm -rs '/special/regular/g' -dp -1 *

Ele passará por todos os diretórios/subdiretórios (por causa de -dp -1) e substituirá special por regular em seus nomes.

5
Jahid

resposta do speakr foi a pista para mim.

Se usar -execdir para transformar arquivos e diretórios, você também desejará remover -type f do exemplo mostrado. Para soletrar, use:

find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+

Além disso, considere adicionar o sinalizador g (global) à expressão regular se quiser substituir as ocorrências all de special por regular em um determinado nome de arquivo e não apenas a primeira ocorrência. Por exemplo:

find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \+

irá transformar special-special.jpg para regular-regular.jpg. Sem a bandeira global, você terminará com regular-special.jpg.

FYI: GNU A renomeação não é instalada por padrão no Mac OSX. Se você estiver usando o gerenciador de pacotes Homebrew , brew install rename irá remediar isso.

2
U007D

Para aqueles que querem apenas renomear diretórios, você pode usar este comando:

find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;

O tipo de nota agora é d para o diretório e usando -execdir.

Ainda não consegui descobrir como renomear arquivos e diretórios em uma única passagem.

Alguém comentou anteriormente que, depois de renomear a pasta raiz, ela não poderia mais percorrer a árvore de arquivos. Há um switch -d disponível que faz uma passagem de profundidade de baixo para cima, então a raiz seria renomeada por último, eu acredito:

find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;

Na manpage (man find):

 -d      Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be
         acted on before the directory itself.  By default, find visits directories in pre-order, i.e., before their contents.  Note, the
         default is not a breadth-first traversal.
0
LokMac

Aqui está uma outra abordagem que é mais portátil e faz não depende do comando rename (já que pode requerer diferentes parâmetros dependendo das distros).

Ele renomeia arquivos e diretórios recursivamente:

find . -depth -name "*special*" | \
while IFS= read -r ent; do mv $ent ${ent%special*}regular${ent##*special}; done

O que faz

  • use find com o parâmetro -depth para reordenar os resultados, realizando uma travessia depth-first (isto é, todas as entradas em um diretório são exibidas antes do próprio diretório).
  • faça substituições de padrões para apenas modificar a última ocorrência de regular no caminho.

Dessa forma, os arquivos são modificados primeiro e, em seguida, cada diretório pai. 

Exemplo

Dando a seguinte árvore:

├── aa-special-aa
│   └── bb-special
│       ├── special-cc
│       ├── special-dd
│       └── Special-ee
└── special-00

Gere esses comandos mv nessa ordem específica:

mv ./aa-special-aa/bb-special/special-cc ./aa-special-aa/bb-special/regular-cc
mv ./aa-special-aa/bb-special/special-dd ./aa-special-aa/bb-special/regular-dd
mv ./aa-special-aa/bb-special ./aa-special-aa/bb-regular
mv ./aa-special-aa ./aa-regular-aa
mv ./special-00 ./regular-00

Para obter a seguinte árvore:

├── aa-regular-aa
│   └── bb-regular
│       ├── regular-cc
│       ├── regular-dd
│       └── Special-ee
└── regular-00
0
jyvet