Renomeia recursivamente todos os arquivos sem alterar suas extensões?

0

Como renomear recursivamente todos os arquivos em várias camadas de subdiretórios sem alterar suas extensões?

Abaixo está uma versão enfraquecida (para economizar espaço) do que eu tenho. Por razões de argumentação, quero que todos os arquivos tenham o mesmo título, mas mantenham sua extensão original. Nunca há mais do que um único arquivo por diretório, então não há chance de dobrar.

Para simplificar, vamos chamá-los de foo , seguidos por sua extensão atual.

Apenas para esclarecer:
Asset\ 1.pdf , Asset\ 1.png , Asset\ [email protected] , Asset\ 1.svg
Vai se tornar: foo.pdf , foo.png , foo.png , foo.svg
E assim por diante.

Eu normalmente usaria a expansão de parâmetro e um loop for , como:

for f in */*; do mv "$f" "${f%/*}/foo.${f##*.}"; done  

Mas não é recursivo. Então, eu preferiria usar algo com find .. -exec ou similar.

~/Desktop/Project/Graphics/
├── Huge
│   ├── PDF
│   │   └── Asset\ 1.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── Asset\ 1.png
│   │   └── 4x
│   │       └── Asset\ [email protected]
│   └── SVG
│       └── Asset\ 1.svg
├── Large
│   ├── PDF
│   │   └── ProjectAsset\ 2.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── ProjectAsset\ 2.png
│   │   └── 4x
│   │       └── ProjectAsset\ [email protected]
│   └── SVG
│       └── ProjectAsset\ 2.svg
├── Medium
│   ├── PDF
│   │   └── ProjectAsset\ 3.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── ProjectAsset\ 3.png
│   │   └── 4x
│   │       └── ProjectAsset\ [email protected]
│   └── SVG
│       └── ProjectAsset\ 3.svg
├── Small
│   ├── PDF
│   │   └── ProjectAsset\ 4.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── ProjectAsset\ 4.png
│   │   └── 4x
│   │       └── ProjectAsset\ [email protected]
│   └── SVG
│       └── ProjectAsset\ 4.svg
└── Tiny
    ├── PDF
    │   └── Asset\ 5.pdf
    ├── PNG
    │   ├── 1x
    │   │   └── Asset\ 5.png
    │   └── 4x
    │       └── Asset\ [email protected]
    └── SVG
        └── Asset\ 5.svg

30 directories, 20 files
    
por tjt263 20.10.2018 / 10:24

4 respostas

3

É muito parecido com find...-exec : invocar um shell para poder usar a expansão de parâmetro, extrair o diretório PARENT e o EXTENSION para que você possa construir o novo nome como PARENT/NAME.EXTENSION e mover / renomear :

find target_dir -type f -exec sh -c '
h=${1%/*}; mv "$1" "${h}/NAME.${1##*.}"' sh {} \;

Se você quiser executar o acima, execute um echo antes do mv ...

Se você tiver acesso a zsh , poderá executar:

autoload zmv
zmv -n '(**/)(*.*)' '${1}NAME.${2:e}'

remova o -n se estiver satisfeito com o resultado.

    
por 20.10.2018 / 18:44
1

Se estiver usando o bash, sua ideia pode percorrer todos os diretórios:

$ shopt -s globstar
$ for f in ./Desktop/**/*; do [[ -f $f ]] && 
           mv -n "$f" "${f%/*}/foo.${f##*.}"; done

Adicionou -n a mv para evitar a substituição de arquivos existentes (se houver).

Isso também pode ser feito com find (em uma chamada ao shell (mais rápido que um shell por arquivo)):

$ find ./Desktop -type f -exec sh -c '
       for f; do echo mv -n "$f" "${f%/*}/foo.${f##*.}"; done' findsh {} \+

Remova o echo se o comando fizer o que você precisa.

    
por 20.10.2018 / 21:17
0

Talvez eu esteja simplificando demais, mas, se você souber a profundidade máxima da hierarquia de diretórios (aqui: 3), por que não

for f in */* */*/* */*/*/*; do ... ; done 

adicionando alguma verificação de erros?

    
por 20.10.2018 / 14:10
0

Localizando todos os arquivos regulares dentro ou abaixo do diretório ~/Desktop/Project/Graphics cujos nomes começam com Asset 1 e substituem essa parte do nome pela string foo :

find ~/Desktop/Project/Graphics -type f -name 'Asset 1*' -exec sh -c '
    for pathname do
        dir=${pathname%/*}
        name=${pathname##*/Asset 1}
        mv -i "$pathname" "$dir/foo$name"
    done' sh {} +

Acima, $name será a parte do nome do arquivo original com Asset 1 removida desde o início.

Para substituir todo o nome do arquivo, mas manter o sufixo do nome do arquivo (e também corresponder a qualquer arquivo que comece com Asset (com espaço após a palavra)):

find ~/Desktop/Project/Graphics -type f -name 'Asset *' -exec sh -c '
    for pathname do
        dir=${pathname%/*}
        name=${pathname##*.}
        mv -i "$pathname" "$dir/foo$name"
    done' sh {} +

Relacionados:

por 24.10.2018 / 09:59