Para todos os diretórios - renomeie todos os subdiretórios com um prefixo

2

Atualmente tenho 2000 diretórios de usuários e cada um desses diretórios tem subdiretórios.

user_1

--- > child1

--- > child2

user_29

--- > criança37

--- > criança56

etc

Eu preciso percorrer todas as pastas de usuários e, em seguida, através de cada uma das pastas filhas e renomear as pastas filhas com um prefixo 'álbum_'. Minha estrutura final deve ser:

user_1

--- > album_child1

--- > album_child2

user_29

--- > album_child37

--- > album_child56

Consegui renomear as pastas de usuários com o seguinte comando:

for f in * ; do mv "$f" user_"$f" ; done;

Eu tenho tentado várias abordagens diferentes para renomear os subdiretórios, como:

find . -maxdepth 2 -mindepth 2 -type d -exec mv '{}' album_'{}'

A primeira parte da consulta acima retorna todos os diretórios que eu preciso renomear ('find. -maxdepth 2 -mindepth 2 -type d').

Como eu acesso o nome do diretório na função -exec e depois adiciono um prefixo a ele?

    
por Robert 16.09.2016 / 08:12

4 respostas

1

Tente:

find . -maxdepth 2 -mindepth 2 -type d -execdir bash -c 'mv "$1" "./album_${1#./}"' mover {} \;

Notas:

  1. Para formar o nome do diretório de destino, precisamos remover o ./ inicial que estará no nome do diretório. Para isso, usamos a remoção do prefixo do shell : ${1#./} .

  2. Usamos -execdir em vez de -exec porque é mais robusto no caso de os diretórios serem renomeados enquanto o comando é executado.

  3. Na expressão bash -c '...' mover {} , bash executa o comando entre aspas simples com $0 atribuído a mover e $1 atribuído ao nome do arquivo, {} . $0 não é usado, a menos que o shell precise gravar uma mensagem de erro.

  4. Não precisamos de nenhum recurso bash para esse código. Qualquer shell POSIX pode ser usado.

  5. Se você quiser testar o comando antes de executá-lo para ter certeza de que deseja fazer o quê, adicione echo da seguinte forma:

    find . -maxdepth 2 -mindepth 2 -type d -execdir bash -c 'echo mv "$1" "./album_${1#./}"' mover {} \;
    

Notas sobre -exec mv '{}' album_'{}'

  1. Não cite o {} . find lida com isso.

  2. Como o nome do arquivo fornecido por find começará com ./ , o formulário album_{} não será bem-sucedido.

Exemplo

Vamos considerar esses diretórios:

$ ls *
user1:
child1  child2

user2:
child1  child2
Press any key to continue...

Agora. vamos executar nosso comando e ver os novos nomes de diretório:

$ find . -maxdepth 2 -mindepth 2 -type d -execdir bash -c 'mv "$1" "./album_${1#./}"' mover {} \;
$ ls *
user1:
album_child1  album_child2

user2:
album_child1  album_child2
    
por 16.09.2016 / 08:18
1

Se você tem perl com base em rename

find -maxdepth 2 -mindepth 2 -type d -exec rename -n 's|.*/\K|album_|' {} +
  • .*/ corresponde até o último / no caminho do diretório
  • usando \K lookbehind, podemos evitar a necessidade de grupo de captura neste caso
  • O . em find . pode ser ignorado como find funciona no diretório atual por padrão

Remova a opção -n da renomeação depois que ela aparecer na renomeação correta

Exemplo:

$ ls *
user_1:
child1  child2

user_29:
child37  child56

$ find -maxdepth 2 -mindepth 2 -type d -exec rename -n 's|.*/\K|album_|' {} +
rename(./user_29/child37, ./user_29/album_child37)
rename(./user_29/child56, ./user_29/album_child56)
rename(./user_1/child2, ./user_1/album_child2)
rename(./user_1/child1, ./user_1/album_child1)
$ find -maxdepth 2 -mindepth 2 -type d -exec rename 's|.*/\K|album_|' {} +

$ ls *
user_1:
album_child1  album_child2

user_29:
album_child37  album_child56
    
por 16.09.2016 / 09:20
0

Eu normalmente não uso diretamente o --exec porque é mais difícil de depurar se algo der errado. Apenas deixe find escrever um script que você possa revisar antes de executar:

find . -maxdepth 2 -mindepth 2 -type d -printf 'mv "%P" "%h/album_%f"\n' > /tmp/rename.sh sh /tmp/rename.sh

    
por 16.09.2016 / 08:25
0

Se tivermos renomeado baseado em Perl instalado,

rename 's!(.*/)!$1album_! if(-d $_)' user*/*
    
por 16.09.2016 / 10:00