Primeiro de tudo,
Não consigo reproduzir os resultados que você afirma para o comando mostrado.
Eu tenho os arquivos sendo renomeados para another directory_file1.jpg
,
another directory_file2.jpg
, etc.
, mas ainda sob os diretórios some directory
.
Em segundo lugar, devido à profundidade da sua estrutura de diretórios,
você deve estar usando -mindepth 4
em vez de 2
.
Em terceiro lugar, eu recomendo strongmente que você use -type f
.
Enquanto você estiver usando -name '*.jpg'
,
você provavelmente não encontrará nenhum diretório.
Mas daqui a seis a oito semanas,
você verá isso e pensar "Quero que isso se aplique a todos os meus arquivos
- Eu não preciso dizer -name '*.jpg'
, e você vai tirar.
E então, se você não tiver -type f
,
o comando find
pode começar a localizar diretórios e renomeá-los.
E modificando uma árvore de diretórios enquanto você a escaneia
é uma receita para o desastre
(como o proverbial "pilotar o avião enquanto ainda o estamos construindo").
Em quarto lugar, o comando rename para mover um arquivo em três níveis
e prefixar seu nome com Directory <num>_
is
rename -n 's!/[^/]+/[^/]+/([^/]+)$!_$1!' (optionally)
porque /[^/]+
representa um nível de diretório
então eu adicionei mais duas cópias disso.
Aviso: Isto irá, como eu disse, mover um arquivo em três níveis.
Se você tem algum arquivo mais profundo na árvore de diretórios do que isso,
eles não serão renomeados para o nível superior;
eles podem ser renomeados para algo como Directory 3/some directory_file3.jpg
.
Mas isso é fácil de corrigir.
Para mover um arquivo para o nível superior de qualquer profundidade em ,
e prefixar seu nome com Directory <num>_
,
é só usar
s!(\./[^/]+)/.*/([^/]+)$/$1_$2/!
TL; DR
Então,
O comando final é
find . -mindepth 4 -type f -exec rename -n 's!/[^/]+/[^/]+/([^/]+)$!_$1!' {} +
Adicione -name '*.jpg'
se você quiser.
Exclua -n
quando a saída de rastreamento mostrar que está fazendo a coisa certa.
Tenha em atenção que isto tem potencial para ter colisões de nomes de ficheiros. Se você tiver arquivos
Directory 1/some directory/another directory/sunrise.jpg
e
Directory 1/some directory/another directory/mountains/sunrise.jpg
este comando tentará renomeá-los para Directory 1_sunrise.jpg
.
Felizmente, o programa rename
parece ser inteligente / amigável o suficiente
não fazer mal neste caso.
O primeiro desses arquivos que ele verá (provavelmente) será renomeado;
os outros serão deixados onde estão (e você será notificado).
(Você pode usar -f
ou --force
para forçar a substituição de arquivos existentes.)
Mas lembre-se de que alguns outros programas (por exemplo, mv
)
tem ações padrão menos amigáveis.
Para a pergunta atualizada
("Como posso incluir todos os nomes de diretório nos nomes dos arquivos?"):
isso é um pouco mais complicado.
Vou assumir explicitamente que estamos pesquisando .
,
então todos os nomes de caminho começarão com ./
.
E eu descobri que o argumento perlexpr para rename
pode realmente conter vários comandos de modificação de string.
Então podemos mover todos os arquivos para o nível superior
e prefixar seus nomes com todos os nomes de diretório no caminho com
s!^\./!!;s!/!_!g
Isso também tem a possibilidade de colisões de nomes de arquivos.
Directory 1/abc/def_ghi/sunrise.jpg
e
Directory 1/abc_def/ghi/sunrise.jpg
(potencialmente) ambos serão renomeados para Directory 1_abc_def_ghi_sunrise.jpg
.
Aviso: Eu testei isso, mas não completamente. Eu não garanto que isso funcionará perfeitamente. Você deve fazer um backup completo antes de tentar os comandos acima.