Esperando que la pregunta se traslade al sitio apropiado, responderé aquí sin embargo.
Se podría añadir una tubería con awk
:
rsync ... | awk '{ $1=$2=$3=$4=""; print substr($0,5); }' >output.txt
Esto elimina toda la información no deseada mediante la salida de todo, desde el campo quinto, pero sólo funciona si ninguno de los primeros cuatro campos en el formato de salida se pone un adicional espacios en blanco en algún lugar (lo cual es poco probable).
Esta solución awk
no funcionará si hay nombres de archivo que comiencen con espacios en blanco.
Una forma aún más robusta de resolver podría ser un programa bastante complejo que también hace suposiciones.
funciona de esta manera: Para cada línea,
- Corte los primeros 10 bytes. Verifique que vayan seguidos de una cantidad de espacios. Cortarlos también.
- Corta todos los dígitos siguientes. Verifique que estén seguidos por un espacio. Corta eso también.
- Corta los siguientes 19 bytes. Verifique que contengan una fecha y una marca de tiempo en el formato apropiado. (No sé por qué los componentes de la fecha están separados con
/
en lugar de -
- no es compatible con ISO 8601.)
- Compruebe que ahora haya un espacio más. Corta eso también. Deje intactos los siguientes espacios en blanco, ya que pertenecen al nombre del archivo.
- Si la prueba ha pasado todas estas verificaciones, es probable que el resto de esa línea contenga el nombre del archivo.
Se vuelve aún peor: para casos de esquina muy esotéricos, hay aún más cosas a tener en cuenta: Los nombres de archivo se puede escapar. Ciertos bytes no imprimibles son reemplazados por una secuencia de escape (#ooo
con ooo
siendo su código octal), un proceso que debe revertirse.
Por lo tanto, ni awk
ni un simple script sed
harán aquí si queremos hacerlo correctamente.
En cambio, la siguiente secuencia de comandos de Python se puede utilizar:
def rsync_list(fileobj):
import re
# Regex to identify a line
line_re = re.compile(r'.{10} +\d+ ..../../.. ..:..:.. (.*)\n')
# Regex for escaping
quoted_re = re.compile(r'\\#(\d\d\d)')
for line in fileobj:
match = line_re.match(line)
assert match, repr(line) # error if not found...
quoted_fname = match.group(1) # the filename part ...
# ... must be unquoted:
fname = quoted_re.sub(# Substitute the matching part...
lambda m: chr(int(m.group(1), 8)), # ... with the result of this function ...
quoted_fname) # ... while looking at this string.
yield fname
if __name__ == '__main__':
import sys
for fname in rsync_list(sys.stdin):
#import os
#print repr(fname), os.access(fname, os.F_OK)
#print repr(fname)
sys.stdout.write(fname + '\0')
Esto da salida a la lista de nombres de archivos separados por caracteres NUL, de forma similar a la forma en find -print0
y muchas otras herramientas de trabajo de modo que incluso un nombre de archivo que contiene un carácter de nueva línea (¡que es válido!) se retiene correctamente:
rsync . | python rsf.py | xan -0 stat -c '%i'
muestra correctamente el número de inodo de cada archivo dado.
Ciertamente, me puedo haber perdido una u otra caja de esquina que no pensé, pero creo que la secuencia de comandos maneja correctamente la mayoría de los casos (probé con todos los 255 nombres de un byte imaginables, así como una nombre de archivo comenzando con un espacio).
Este es un buen ejemplo de lo que está mal con (correcciones y qué PowerShell) * conchas nix populares . –
Otra redacción potencial de preguntas: ¿cómo se filtra 'find' usando' rsync' include y exclude syntax? –