pax, opção de cadeia de substituição inválida

1

Estou com dificuldades para entender o que está acontecendo em um script Perl que usa pax .

Plano de fundo: Alimentando um arquivo .tgz para pax e descompactando para obter uma pasta cheia de arquivos.

Isso é o que eu não entendo:

pax -r -z -s '/.*\//directory\//p' -f $input_path/$tgz

Onde $input_path é uma variável escalar em Perl contendo um caminho e $tgz é outra variável escalar contendo o nome do arquivo .tgz .

Portanto, -r para leitura faz sentido, -z para descompactar está bom. As bandeiras -s e -f me confundem. Estou tendo o erro a seguir: %código%.

Como acho que as bandeiras funcionam:

pax: Invalid replacement string option /.*\//directory\//p , pois isso não parece ser o problema. Este é apenas o lugar onde colocar os arquivos.

-f , substituição de string para modificar os nomes do arquivo contido no arquivo -s .

Alguém pode desmistificar a parte .tgz , já que eu não entendo o que está acontecendo aqui com todas as barras de escape, /.*\//directory\//p e \ devem fazer alguma coisa, mas não tenho ideia do quê?

    
por Christopher 05.10.2016 / 10:18

1 resposta

2

O Pax analisa /.*\//directory\//p como:

  • / é o caractere separador.
  • .*\ é a expressão regular, correspondendo a qualquer sequência que termina com uma barra invertida (a barra invertida cita o próximo caractere).
  • / separa a expressão regular do texto de substituição.
  • / termina o texto de substituição.
  • directory\//p está perdendo lixo.

Evidentemente, você pretendia usar as barras invertidas para proteger as barras de modo que elas fizessem parte da regex em vez de separadores. Para um script de shell, há barras invertidas extras lá (mas podem ser devido ao fato de que isso está acontecendo em um script perl, mais sobre isso mais tarde). Há também algo de errado com as barras. Se você quiser remover any/leading/prefix/up/to/directory dos caminhos, então deve ser

pax -r -z -s '/.*\/directory\///p' -f "$input_path/$tgz"

Seria mais fácil ler com um separador diferente. Então você não precisaria escapar de barras.

pax -r -z -s '!.*/directory/!!p' -f "$input_path/$tgz"

Tudo isso assume que o comando é um comando shell . Você menciona um script Perl; O Perl adicionaria sua própria camada de cotação, então o que escrever depende de como a string é inserida no script Perl. O uso de $input_path/$tgz é definitivamente problemático porque está interpolando uma string em um script de shell, de modo que a string será analisada como um fragmento de shell em vez de um nome de arquivo.

Se o comando shell estiver entre aspas duplas ou backticks, as barras invertidas precisam ser duplicadas. Ainda há o problema da barra perdida. Aqui está uma maneira de escrever isso em Perl:

my $quoted_file_name = quotemeta("$input_path/$tgz");
system("pax -r -z -s '!.*/directory/!!p' -f $quoted_file_name");

Se você estiver usando system , use o formulário de lista para evitar problemas de cotação, não invocando um shell intermediário.

system('pax', '-r', '-z', '-s', '!.*/directory/!!p', '-f', "$input_path/$tgz");
    
por 07.10.2016 / 08:50