pax, opción de cadena de reemploop no válida

Me cuesta un poco entender lo que sucede en un script de Perl que usa pax .

Antecedentes: Alimentando un file .tgz a pax y desempacando para get una carpeta llena de files.

Esto es lo que no entiendo:

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

Donde $input_path es una variable escalar en Perl que contiene una ruta y $tgz es otra variable escalar que contiene el nombre del file .tgz .

Entonces -r para leer tiene sentido, -z para descomprimir está bien. Las banderas -s y -f me confunden. Me pax: Invalid replacement string option /.*\\//directory\\//p el siguiente error: pax: Invalid replacement string option /.*\\//directory\\//p .

Cómo creo que funcionan las banderas:

-f , ya que este no parece ser el problema. Aquí es donde poner los files.

-s , reemploop de cadena para modificar los nombres del file contenido en el file .tgz .

¿Puede alguien desmitificar la parte /.*\\//directory\\//p , ya que realmente no entiendo lo que está pasando aquí con todas las barras de escape, y la p debe hacer algo pero no tengo ni idea de qué?

Pax analiza /.*\\//directory\\//p como:

  • / es el caracter separador.
  • .*\\ es la expresión regular, que coincide con cualquier cadena que termine con una barra diagonal inversa (la barra invertida cita el siguiente carácter).
  • / separa la expresión regular del text de reemploop.
  • / finaliza el text de reemploop.
  • directory\\//p está arrastrando basura.

Evidentemente, pretendía utilizar las barras diagonales inversas para proteger las barras diagonales para que formen parte de la expresión regular en lugar de separadores. Para un script de shell, hay barras invertidas adicionales allí (pero pueden deberse al hecho de que esto está sucediendo en un script de Perl, más sobre esto más adelante). También hay algo mal con las barras. Si desea eliminar any/leading/prefix/up/to/directory de las routes, entonces debería ser

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

Sería más fácil de leer con un separador diferente. Entonces no necesitarías escaping de las barras.

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

Todo esto supone que el command es un command de shell . Usted menciona una secuencia de commands Perl; Perl agregaría su propia capa de comillas, entonces, qué escribir depende de cómo se inserta la cadena en el script de Perl. El uso de $input_path/$tgz es definitivamente problemático porque está interpolando una cadena en un script de shell, por lo que esa cadena se analizará como un fragment de shell en lugar de un nombre de file.

Si el command de shell está entre comillas dobles o retrocesos, entonces las barras diagonales inversas necesitan doblar. Todavía existe el problema de la barra de misplaces. Aquí hay una manera de escribir esto en Perl:

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

Si está utilizando el system , debe utilizar el formulario de list para evitar problemas de cotización al no invocar un intérprete intermedio.

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