Script de shell para renomear vários arquivos de seu nome de pastas pai

3

Eu tenho uma estrutura de arquivos como esta:

  • 00000010
    • 000000001.file1
    • 000000001.file2
  • 00000020
    • 00000003.file1
    • 00000003.file2
    • 00000003.file3
  • ...

Portanto, há pastas com nomes de 8 dígitos contendo um ou mais arquivos com nome começando com números de 8 dígitos. Mas esses nomes de arquivos são - digamos - fora de sincronia. Então agora eu tento renomeá-los recursivamente no bash para arquivar:

  • 00000010
    • 000000010.file1
    • 000000010.file2
  • 00000020
    • 00000020.file1
    • 00000020.file2
    • 00000020.file3
  • ...

Meu script se parece com:

#! /bin/bash

find * -maxdepth 1 -name "*" -type d | while read -r dir
do
        rename 's/$dir\/[0-9]{8}/$dir/' *
done

Mas isso não está funcionando e dá erros como

Global symbol "$dir" requires explicit package name at (eval 1) line 1.

Como eu poderia escrevê-lo para renomear os arquivos de acordo com os nomes das pastas?

Obrigado pela ajuda!

    
por Simon 01.02.2011 / 10:56

2 respostas

2

Como de outra resposta eu aprendi, eu tenho que usar

rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*

Apenas no caso de alguém ter o mesmo problema ...

    
por 01.02.2011 / 11:23
0

Eu realmente não gosto da resposta onde $dir é interpolado no padrão. Isso poderia levar a resultados inesperados se o diretório, por exemplo, contém um caractere que é interpretado como um token de expressão especial.

Eu preferiria combinar os arquivos diretamente no padrão, negando a necessidade de fazer um loop sobre os diretórios e apenas usar um glob regular.

rename 's#([^/]+)/[^/]+(\.file[0-9]+)$#$1/$1$2#' base_directory/*/*

onde o glob atinge os arquivos individuais dentro dos diretórios (pode até ser especificado para base_directory/*/*.file* , ou similar, mas não importa aqui).

Observe que este é o comando completo, sem a necessidade da construção find .

  • Eu uso # como separador em vez do "regular" / para evitar ter que escapar disso nos padrões.
  • Eu capturei o grupo (ganancioso) de "não um separador de diretório", seguido por um separador de diretório, seguido por um nome de arquivo e um fim de linha. Isso faz com que o primeiro grupo de captura seja o diretório pai de cada arquivo.
  • A primeira parte do nome do arquivo é descartada, exceto a finalização para manter o sufixo ordinal.

Eu escolhi usar uma abordagem mais geral do que assumir que os arquivos tinham 8 caracteres, mas a verdadeira diferença é que eu não preciso da find nem de empinar a variável $dir na (possivelmente insegura ambiente de regexp.

    
por 02.04.2015 / 09:22