renomear (1) script semelhante ao Perl, mas para copiar arquivos?

3

Portanto, há este rename(1) Perl thing . Isso se encaixa na minha tarefa com precisão, exceto que eu preciso basicamente de cp arquivos em vez de mv .

Como conseguir isso? Eu tenho algumas regras de renomeação, todas expressas de forma compacta em s|/foodir/|/|;s|/bardir/|/| form e, em seguida, algumas linhas de padrões de arquivo que eu preciso copiar para copiar.

Parece um pouco assim:

rename -v 's|/pars/|/|; s|/fts/|/|; s|innobase/include|include|' \
    storage/{innobase,xtradb}/pars/{pars0grm.cc,pars0grm.y,pars0lex.l,lexyy.cc} \
    storage/{innobase,xtradb}/fts/{fts0blex.cc,fts0blex.l,fts0pars.cc,fts0pars.y,fts0tlex.cc,fts0tlex.l} \
    storage/innobase/include/fts0[bt]lex.h
    
por ulidtko 16.06.2016 / 11:36

3 respostas

3

Isso é um trabalho para pax . pax é um comando POSIX padrão; Algumas distribuições do Linux omitem a partir da instalação padrão, então você pode precisar instalar o pacote explicitamente. Você não obtém o poder total do Perl, apenas a substituição básica do regex, mas isso é bom o suficiente para o seu caso de uso.

pax -rw -pe -s'|/pars/|/|' -s'|/fts/|/|' -s'|innobase/include|include|' …

Se você quiser algo mais poderoso, zmv do zsh . Existem muitos exemplos neste site , por exemplo Traverse, copy & transformar nomes de arquivos , como renomear arquivos ao copiar

    
por 17.06.2016 / 02:18
1

Como você, eu não quero uma ferramenta ou sintaxe diferente, quero copy com exatamente a mesma sintaxe que rename ! Acabei de responder a esta aqui . Postando aqui por conveniência:

Eu realmente gosto da sintaxe regex do script rename perl (por Robin Barker e Larry Wall), por exemplo:

rename "s/OldFile/NewFile/" OldFile*

OldFile.c and OldFile.h are renamed to NewFile.c and NewFile.h, respectively

Eu simplesmente queria exatamente a mesma coisa com um comando de cópia:

copy "s/OldFile/NewFile/" OldFile*

Então eu dupliquei esse script e mudei a instrução renomear para copiar via File::Copy . E voila! Um comando de cópia com a sintaxe perl-regex:

link

    
por 06.04.2018 / 19:18
0

OK, então consegui me safar com o antigo sed como este.

ls -1 \
    storage/{innobase,xtradb}/pars/{pars0grm.cc,pars0grm.y,pars0lex.l,lexyy.cc} \
    storage/{innobase,xtradb}/fts/{fts0blex.cc,fts0blex.l,fts0pars.cc,fts0pars.y,fts0tlex.cc,fts0tlex.l} \
    storage/innobase/include/fts0[bt]lex.h \
    | sed -re 'h; s|/pars/|/|; s|/fts/|/|; s|innobase/include|include|; H; x; s|\n| |' \
    | xargs -L1 cp -v \
    ;

O script sed não é tão trivial, portanto, deixe-me explicar passo a passo (para o futuro eu):

  • h copia a linha atual ("espaço de padrão") em um registrador ("espaço de espera");
  • cada s edita o espaço padrão como de costume, o espaço reservado não muda;
  • H acrescenta a linha agora editada ao registrador de espera - que contém duas linhas, o nome do arquivo antigo e o novo, com caracteres \n embutidos, claro ;
  • x troca o espaço de armazenamento com espaço de padrão, carregando efetivamente o par antigo-novo do registrador de espera;
  • s|\n| | achata as duas linhas em uma, separando-as com espaço;
  • e, finalmente, um p implícito (da chamada sed sem -n ) imprime o resultado.

No total, o pipeline funciona da seguinte maneira:

  • ls -1 expande todos os globs em nomes de arquivos reais existentes e os imprime um por linha;
  • sed transforma isso em "$old_filename $new_filename" , novamente um arquivo por linha;
  • xargs -L1 chama cp -v $old_filename $new_filename em todas as linhas.

É isso aí!

    
por 16.06.2016 / 16:14