Renomeia um monte de arquivos, alterando vários substrings [duplicados]

0

Eu tenho um monte de arquivos com nomes como image (1) image (2) image (3). Eu gostaria de renomear aqueles em massa ao longo das linhas de image1.jpg image2.jpg etc. Eu posso fazer isso em duas etapas por meio de chaves, que aparentemente é algum tipo de provisão de shell embutida para substituição de string ao longo das linhas de

orig="a_string"
mod=${orig/string/new_thing}

que leva a_string para a_new_thing. Então, usando isso em um loop for eu posso cuidar de transformar o) em .jpg

for f in *; do mv $f "${f/)/.jpg}" ;done

e depois

for f in *; do mv $f "${f/\(/}" ;done

remove o (. O paren aberto tem que ser escapado, suponho que caso contrário o shell pensa que é o começo de outra coisa. O paren próximo não precisa ser escapado desse jeito.  Então, a minha pergunta é, existe um one-liner ou outra maneira melhor de fazer isso, como usar pipes. Se os parêntesis no nome do arquivo estiverem copiando as coisas, então assuma por enquanto que esses parêntesis são removidos, deixando o simples problema de substituir duas substrings por duas outras strings.

    
por jeremy_rutman 22.11.2016 / 22:02

3 respostas

1

Você pode renomear arquivos múltiplos usando o comando rename . Neste caso, uma solução de trabalho poderia ser:

rename 's/\(//; s/\)/.jpeg/;' image*
    
por 22.11.2016 / 22:15
0

Você pode alterar mais de uma coisa por vez usando uma barra dupla.

for f in * ; do mv "$f" "${f//[()]/}.jpg" ; done
    
por 22.11.2016 / 22:13
0

Vou abordar sua pergunta geral sobre como fazer várias substituições (especificamente, em uma renomeação, embora isso possa ser aplicável a outros contextos). Eu suponho que você tenha um monte de arquivos cujos nomes incluem as palavras "over" e "dog", e você quer substituí-los por "under" e "cat", respectivamente.

Força bruta:

for f in *
do
    g=${f/over/under}
    h=${g/dog/cat}
    mv -- "$f" "$h"
done

(O -- protege você contra comportamento indesejado Isso pode resultar de um nome de arquivo que começa com - . Altere a última linha para mv -- "$f" "$h".jpg , se desejar. Observe que, se um nome de arquivo contiver somente , “over” ou “dog” (mas não ambos), isso fará apenas a substituição disponível. Se contiver “dog” e “over” (nessa ordem), ainda fará as substituições. No caso que você apresentou, onde suas strings são "(" e ")", você pode não gostar desses comportamentos.

P.S. Realisticamente, provavelmente você deve proteger o comando mv assim:

if [ "$f" != "$h" ]
then
    if [ -e "$h" ]
    then
        (Error handling)
    else
        mv -- "$f" "$h"
    fi
done

para evitar uma mensagem de erro ao tentar renomear um arquivo para si (porque seu nome não continha das strings), e para evitar a destruição de um arquivo existente (por exemplo, se você tiver um arquivo image(1) e você também já tem um arquivo image1.jpg ).

com sed

for f in *
do
    g=$(sed 's/\(.*\)over\(.*\)dog\(.*\)/undercat/' <<< "$f")
    mv -- "$f" "$g"
done

Este é o oposto do primeiro: faz as substituições apenas se "over" e "dog" ambos aparecerem (nessa ordem) e não o contrário.

A sintaxe <<< ("string aqui") não funciona em todos os shells. Para fazer o acima em um shell que não suporta aqui strings, faça:

for f in *
do
    g=$(printf "%s" "$f" | sed 's/\(.*\)over\(.*\)dog\(.*\)/undercat/')
    mv -- "$f" "$g"
done
    
por 23.11.2016 / 03:00