Por que 'renomear' se comporta de maneira diferente sempre que eu uso o caminho completo em vez do caminho atual?

1

Ok, eu estou respondendo uma pergunta onde o OP tem vários repositórios no Ubuntu que podem estar causando problemas ao instalar software não relacionado. Eu recomendo desabilitar os PPA's usando um único liner rename e depois seguir uma série de instruções. Tudo bem, e deixo essa pergunta para trás como respondida ... não. Resultados que rename não se comportaram como eu esperava:

sudo rename s/list/list\.disable/g /etc/apt/sources.list.d/*.list

Com isso, espero renomear para analisar /etc/apt/sources.list.d/ de qualquer arquivo que termine em .list e substitua o .list por .list.disable . Eu tive outra resposta com quase o mesmo comando, mas OP nunca deu feedback, e eu estou meio que jogando a teoria sem testar primeiro. Então, é por minha surpresa que OP encontra problemas com a linha:

Can't rename /etc/apt/sources.list.d/iaz-battery-status-quantal.list /etc/apt/sources.list.disable.d/iaz-battery-status-quantal.list.disable: No such file or directory
Can't rename /etc/apt/sources.list.d/ubuntu-wine-ppa-quantal.list /etc/apt/sources.list.disable.d/ubuntu-wine-ppa-quantal.list.disable: No such file or directory
Can't rename /etc/apt/sources.list.d/webupd8team-java-raring.list /etc/apt/sources.list.disable.d/webupd8team-java-raring.list.disable: No such file or directory

Eu tenho uma sensação estranha, então testo a teoria e vejo o mesmo resultado. Então, sempre que você obtiver um problema é normalmente regex, não ? Eu mudei o regex de muitas formas distorcidas:

  • s / .list / .list.disable / g
  • s / .list / .list.disable / g
  • /list/list.disable /
  • outras combinações que não lembro

Bem, eu decidi que regex não era o problema, então eu olhei para o seletor, e mudei para /etc/apt/sources.list.d/* e reciclei o teste de regex. Sem alegria. Ficando um pouco frustrado eu faço touch some.list e aplico meu comando

rename s/\.list/\.list\.disable/g *

Bingo! Agora me sinto trollado por toda parte. Conserto minha resposta e continuo com minha vida ... não! Isto não é aceitável. Por quê? Eu procuro o manual que, para minha surpresa, usa apenas exemplos de caminhos atuais. Isso é normal? Ou é só que a função não foi implementada? Ou eu deveria começar a desconfiar de minhas teorias?

    
por Braiam 27.09.2013 / 22:41

2 respostas

8

Use o parâmetro -n para executar rename em um modo de execução seca que é muito útil quando você deseja testar seu padrão:

martin@martin ~ % rename -n s/list/list.disable/g /etc/apt/sources.list.d/*.list | sed 's/renamed as/\n =>/g'
[...]
/etc/apt/sources.list.d/spotify.list 
 => /etc/apt/sources.list.disable.d/spotify.list.disable
/etc/apt/sources.list.d/steam.list 
 => /etc/apt/sources.list.disable.d/steam.list.disable
[...]

O erro óbvio aqui é que o padrão list corresponde a sources.list.d , então você está tentando renomear a pasta e seus arquivos contidos.

Use este padrão:

rename -n 's/\.list$/.list.disable/' /etc/apt/sources.list.d/*.list | sed 's/renamed as/\n =>/g'
[...]
/etc/apt/sources.list.d/spotify.list 
 => /etc/apt/sources.list.d/spotify.list.disable
/etc/apt/sources.list.d/steam.list 
 => /etc/apt/sources.list.d/steam.list.disable
[...]

As diferenças são:

  1. A citação de . no padrão de pesquisa como \. garante que o ponto corresponda apenas a um ponto real e não a qualquer caractere (é o que um ponto sem aspas geralmente faz em um regex).

  2. A lista $ after significa "fim da string". Ele garante que apenas a ".list" no final do nome do arquivo corresponda e seja substituída, não uma ".list" que esteja em algum outro lugar no caminho ou no nome do arquivo.

  3. Você não precisa citar o ponto na string de substituição; ".list.disable", portanto, funciona sem barras invertidas, porque o . não tem mais um significado especial.

  4. Observe também que citei o regex entre aspas simples para impedir que o shell o modifique de alguma forma.

por 27.09.2013 / 22:55
1

O problema é usar o switch global g quando você realmente deveria ter ancorado o padrão. Como você escreveu:

s/a/b/g

substitui todos os a com b em todos os lugares da string. Isso está fazendo com que você tente renomear para caminhos para os quais nenhum diretório existe. É também por isso que o problema desapareceu quando você fez a operação dentro do diretório para que houvesse apenas uma correspondência para substituir.

Eu acho que você pode ter pretendido ancorar o padrão

s/\.list$/.list.disable/

que teria impedido a tentativa de mover um arquivo para o diretório /etc/apt/sources.list.disable.d/ que não existe (assim você não pode mover um arquivo para ele).

    
por 27.09.2013 / 22:50