Como renomeio centenas de arquivos para todos incluem a mesma palavra no início do nome do arquivo? [fechadas]

1

Aqui está uma pequena amostra dos arquivos que eu preciso renomear:

    ID_EDMSCP_20160815.txt.pgp
    ID_EDMSCP_20160816.txt.pgp
    ID_EDMSCP_20160817.txt.pgp
    ID_EDMSCP_20160818.txt.pgp       

Eu criei um script da pergunta de outra pessoa da seguinte forma:

    for file in ID_EDMSCP_*.txt.pgp
    do
        mv -i "${file}" "${file/-ID-/-SUBMIT_GO_ID-}"
    done

No entanto, estou recebendo o seguinte:

    mv: 'ID_EDMSCP_20160815.txt.pgp' and 'ID_EDMSCP_20160815.txt.pgp' are the same file

E nada está sendo renomeado. Estou faltando alguma coisa?

    
por kirby willis 23.08.2016 / 17:22

3 respostas

6

mv -i "${file}" "${file/-ID-/-SUBMIT_GO_ID-}"

Essa substituição de cadeia diz para substituir -ID- , o que não ocorre nos nomes dos arquivos de origem. Acho que você quer dizer isso em vez disso:

mv -i "${file}" "${file/ID_/SUBMIT_GO_ID_}"

Outro problema que você pode ter é que este é um recurso ksh93 , também disponível em Bash e Zsh, mas não em shells POSIX puros . Se você estiver usando #!/bin/sh no topo do script, ele será executado sob um shell POSIX ou um interpretador Bourne shell pré-POSIX em alguns sistemas , o que não vai entender isso.

Existem várias alternativas se você não puder usar esse recurso não padrão de shells avançados:

sed

Se você precisar que este script seja portável para todos os sistemas do tipo Unix, poderá alternar para sed para a substituição:

mv -i "$file" "$(echo $file | sed -e 's/^ID_/SUBMIT_GO_ID_/')"

Isso ainda requer pelo menos um shell POSIX, devido ao uso da interpolação de comando $() style, mas é mais fácil "pedir" do que esperar um shell avançado em todos os lugares.

Se o seu script tiver que ser executado em todos os shell do tipo Bourne, você pode alternar para a interpolação do comando de estilo backtick, que pode ser difícil de acertar se você tiver espaços incorporados nos nomes de arquivos, mas isso não parece ser o caso aqui, de acordo com o seu exemplo publicado. Então, isso deve ser equivalente à opção anterior para seus propósitos:

mv -i "$file" 'echo $file | sed -e s/^ID_/SUBMIT_GO_ID_/'

mmv

Outra opção é instalar o mmv , um programa que não navio instalado em qualquer sistema do tipo Unix que eu conheço, mas que geralmente é empacotado para ele no repositório de pacotes padrão. Com mmv , você pode substituir todo o seu loop de script de shell com

$ mmv 'ID_*' 'SUBMIT_GO_ID_#1'

Observe que não há sinalizador -i porque mmv não suporta solicitações para cada renomeação. No entanto, ele verifica previamente todas as renomeações planejadas e tenta detectar problemas antes de começar a trabalhar, portanto, pode estar próximo o suficiente para seus objetivos.

renomear

Ainda outra opção é o comando rename , do qual há pelo menos três variantes em estado selvagem. Existem dois forks do script Perl de Larry Wall com esse nome, um dos quais pode ser instalado em seu sistema como parte de sua distribuição Perl. Em seguida, há a variante util-linux , muitas vezes instalada em vez dessa versão em máquinas Linux ou ao lado dele. Se você tiver ambos instalados, o baseado em Perl provavelmente será chamado de prename para evitar um conflito.

A principal vantagem dos baseados em Perl é que você pode usar expressões regulares Perl , que são mais poderosas do que as expressões glob suportadas por mmv ou as expressões regulares POSIX suportadas por sed . Não importa muito neste caso específico, no entanto, porque a tarefa é trivial:

$ rename '^ID_' SUBMIT_GO_ID_ ID_EDMSCP_*.txt.pgp

A versão util-linux é muito menos capaz porque, embora chame seu primeiro parâmetro de "expressão", não é nem uma expressão regular POSIX nem uma expressão regular Perl. Não é nem uma expressão glob: é apenas uma string literal. Mas como acima, essa limitação não nos atrapalha neste caso particular:

$ rename ID_ SUBMIT_GO_ID_ ID_EDMSCP_*.txt.pgp

Assim como com mmv , rename não suporta o sinal -i .

Casca Bourne velha e simples

Tudo isso dito, seu caso particular permite uma solução muito mais simples, porque seu padrão de entrada aparece no final do padrão de saída, então você pode fazer tudo na sintaxe portável do Bourne shell:

for file in ID_EDMSCP_*.txt.pgp
do
    mv -i "$file" SUBMIT_GO_"$file"
done

Eu deixei as alternativas complicadas acima porque elas são frequentemente necessárias, já que os mecanismos internos dentro da linguagem shell nem sempre são suficientes.

    
por 23.08.2016 / 17:31
2

Tente isto:

for file in ID_EDMSCP_*.txt.pgp
do
    mv -i "${file}" SUBMIT_GO_"${file}"
done
    
por 23.08.2016 / 17:38
1

No Linux, você pode usar o comando rename . É muito limitado, mas é bom o suficiente para este caso de uso simples: substituir a primeira ocorrência de uma substring por uma string diferente.

rename ID SUBMIT_GO_ID ID_EDMSCP_*.txt.pgp

No Debian e derivados (Ubuntu, Mint,…), esse comando é chamado rename.ul . O comando rename nessas distribuições é diferente com uma sintaxe incompatível, também chamada de prename . Com esse comando você pode fazer

prename 's/ID/SUBMIT_GO_ID/' ID_EDMSCP_*.txt.pgp
    
por 24.08.2016 / 01:42