Renomeia arquivos dependendo do seu diretório pai

1

Eu tenho um diretório principal, digamos main . Esse diretório principal tem algumas pastas, dentre as quais três pastas denominadas ccc ddd e lll , que são as únicas pastas que eu quero segmentar e trabalhar. Cada uma dessas subpastas tem algumas pastas dentro das quais todas têm o mesmo nome nas três subpastas, de modo que as subpastas ccc ddd lll contenham pastas com o mesmo nome.

Em seguida, cada uma dessas subconsolidadoras que estão dentro de ccc ddd lll tem vários arquivos nomeados com um determinado nome como este c_000 d_000 l_000 , c_001 d_001 l_001 e assim por diante.

O que quero fazer primeiro é renomear esses arquivos para que o diretório de seus dois pais seja anexado no início do nome do arquivo, assim ccc_foo1_c_000 ddd_foo1_d_000 lll_foo1_l_000 e assim por diante. Estou perguntando se alguém pode me avisar como isso pode ser feito em um script .sh ?

Esta é uma estrutura de árvore simples da minha pasta principal:

.
'-- main
    |-- ccc
    |   '-- foO1
    |   |    |-- c_000
    |   |    '-- c_001
    |   |
         -- foo2
    |       |-- c_000
    |       '-- c_001
    |   
    |   
    |-- ddd
    |   '-- foO1
    |   |    |-- d_000
    |   |    '-- d_001
    |   |
         -- foo2
    |       |-- d_000
    |       '-- d_001
    |-- lll
    |      '-- foO1
    |  |    |-- l_000
    |  |    '-- l_001
    |  |
    |   -- foo2
    |      |-- l_000
    |      '-- l_001
    |
    |-- aaa
    |-- bbb
    
por Tak 12.03.2015 / 15:44

3 respostas

1

Você poderia fazer algo assim:

for dir in ccc ddd lll; do 
    find "main/$dir" -type f -print0 | 
        while IFS= read -r -d '' f; do 
            dd=$(dirname "$f")
            new="${f/main\/}"
            new="${new//\//_}" 
            mv "$f" "$dd"/"$new"
        done
done

Após o script acima, seus arquivos ficarão assim:

.
'-- main
    |-- ccc
    |   |-- fo01
    |   |   |-- ccc_fo01_c_000
    |   |   '-- ccc_fo01_c_001
    |   '-- fo02
    |       |-- ccc_fo02_c_000
    |       '-- ccc_fo02_c_001
    |-- ddd
    |   |-- fo01
    |   |   |-- ddd_fo01_d_000
    |   |   '-- ddd_fo01_d_001
    |   '-- fo02
    |       |-- ddd_fo02_d_000
    |       '-- ddd_fo02_d_001
    '-- lll
        |-- fo01
        |   |-- lll_fo01_l_000
        |   '-- lll_fo01_l_001
        '-- fo02
            |-- lll_fo02_l_000
            '-- lll_fo02_l_001

Explicação

Sugiro que você adicione um echo antes do mv para testar antes de fazer isso.

    
por 12.03.2015 / 16:17
2

Aqui está uma solução shell POSIX simples que faz um loop nos arquivos, analisa as partes do diretório dos nomes e os renomeia um por um.

for x in ccc/*/* ddd/*/* lll/*/*; do
  dir2=${x%/*}; dir1=${dir2%/*}; dir2=${dir2#"$dir1"}
  mv -- "$x" "${x%/*}/${dir1}_${dir2}_${x##*/}"
done

No bash, você pode usar a substituição da string expansão do parâmetro recurso para evitar a necessidade de analisar os nomes dos arquivos.

for x in ccc/*/* ddd/*/* lll/*/*; do
  mv -- "$x" "${x%/*}/${x//\//_}"
done

Em zsh, você pode usar zmv para renomear arquivos com base em padrões.

autoload -U zmv
zmv '(ccc|ddd|lll)/(*)/(*)' '$1/$2/${1}_${2}_$3'
    
por 13.03.2015 / 01:34
0

Para uma solução um pouco mais soft-run do seu diretório main :

#!/bin/bash

for f in $(find . -name '*_00*'); do
    mv "$f" "$(dirname "$f")/$(dirname "${f:2}" | tr "/" "_")_$(basename $f)"
done

Isso deve percorrer todos os diretórios de forma recursiva procurando por todos os arquivos que contenham o padrão *_00* . Cada um desses arquivos é renomeado separadamente com uma combinação que consiste no caminho ( $(dirname $"f") ), o caminho transformado contendo sublinhados e os dois primeiros caracteres removidos ( $(dirname "${f:2}" | tr "/" "_") ) e o nome do arquivo original ( $(basename $f) ).

    
por 27.11.2017 / 18:54