GNU/Linux >> Tutoriales Linux >  >> Linux

Escapar de los caracteres desconocidos de la cadena para -exec?

Tengo un comando de búsqueda que encuentra ciertos archivos y directorios. Ese comando de búsqueda luego ejecuta rsync con los archivos y directorios encontrados previamente como fuente. El problema es que esos archivos y directorios pueden tener todo tipo de caracteres, como comillas simples y dobles, sin mencionar los caracteres ilegales de Windows, etc...

¿Cómo puedo escapar dinámicamente una cadena para usarla en rsync u otros comandos?

Este comando funciona codificando comillas dobles para la cadena de origen de rsync, pero se romperá si la cadena tiene comillas dobles.

find "/mnt/downloads/cache/" -depth -mindepth 1 \( \
-type f \! -exec fuser -s '{}' \; -o \
-type d \! -empty \) \
\( -exec echo rsync -i -dIWRpEAXogt --numeric-ids --inplace --dry-run '"{}"' "${POOL}" \; \)

salida resultante:

rsync -i -dIWRpEAXogt --numeric-ids --inplace --dry-run "test/this " is an issue" /mnt/backing

Comando de trabajo después de la información en las respuestas aplicadas:

find "/mnt/downloads/cache/" -depth -mindepth 1 \( \
                             -type f \! -exec fuser -s {} \; -o \
                             -type d \! -empty \) \
                             \( -exec rsync -i -dIWRpEAXogt --remove-source-files-- "${POOL} \; \) \
                             -o \( -type d -empty -exec rm -d {} \; \)

Respuesta aceptada:

Tu problema de cotización proviene de que intentas resolver un problema que no tienes. La necesidad de citar argumentos solo entra en juego cuando se trata de un shell, y si find está llamando a rsync directamente, no hay caparazón involucrado. El uso de resultados visuales no es una buena manera de saber si funciona o no porque no puede ver dónde comienza y termina cada argumento.

Esto es lo que quiero decir:

# touch "foo'\"bar"

# ls
foo'"bar

# find . -type f -exec stat {} \;
  File: ‘./foo'"bar’
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d    Inode: 1659137     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1004/ phemmer)   Gid: ( 1004/ phemmer)
Access: 2017-12-09 13:21:28.742597483 -0500
Modify: 2017-12-09 13:21:28.742597483 -0500
Change: 2017-12-09 13:21:28.742597483 -0500
 Birth: -

Tenga en cuenta que no cité el {} en el argumento de stat .

Dicho esto, su comando va a tener un rendimiento muy bajo, porque está llamando a rsync para cada archivo coincidente. Hay 2 formas de resolver esto.

Como otros han indicado, puede usar canalizar la lista de archivos a rsync en entrada estándar:

# find . -type f -print0 | rsync --files-from=- -0 . dest/

# ls dest/
foo'"bar

Esto usará bytes nulos como delimitador de nombre de archivo, ya que los archivos no pueden contener bytes nulos en su nombre.

Relacionado:¿Cómo solucionar el error "El dispositivo USB desconocido necesita más energía de la que el puerto puede suministrar"?

Si está utilizando GNU find , tiene otro método para invocar -exec , y eso es -exec {} + . En este estilo find pasará más de un argumento a la vez. Sin embargo, todos los argumentos se agregan al final del comando, no en el medio. Puede abordar esto pasando los argumentos a través de un pequeño shell:

# find . -type f -exec sh -c 'rsync "[email protected]" dest/' {} +

# ls dest/
foo'"bar

Esto pasará la lista de archivos a sh que luego los sustituirá por el "[email protected]"


Linux
  1. Tr analógico para caracteres Unicode?

  2. ¿Un comando para imprimir solo los últimos 3 caracteres de una cadena?

  3. ¿Salir de Find si falla un -exec?

  4. encontrar -exec cmd {} + vs | xargs

  5. Canalice la cadena a la fecha GNU para la conversión:¿cómo hacer que se lea desde la entrada estándar?

Cómo encontrar una cadena en un archivo en Linux

Cómo buscar archivos desde la línea de comandos de Linux

Cómo quitar (^M) caracteres de un archivo en Linux

Eliminar todos los caracteres especiales y mayúsculas y minúsculas de la cadena en bash

cómo buscar un directorio desde la terminal en ubuntu

encontrar comando de PID