python cocoa filenames pyobjc

plot title python



Cree un nombre de archivo(sano/seguro) desde cualquier cadena(insegura) (6)

Quiero crear un nombre de archivo sano / seguro (es decir, algo legible, sin caracteres "extraños", etc.) a partir de una cadena aleatoria de Unicode (mich puede contener cualquier cosa).

(No me importa si la función es Cocoa, ObjC, Python, etc.)

Por supuesto, puede haber infinitos personajes que pueden ser extraños. Por lo tanto, no es realmente una solución tener una lista negra y agregar más y más a esa lista a lo largo del tiempo.

Podría tener una lista blanca. Sin embargo, realmente no sé cómo definirlo. [a-zA-Z0-9 .] es un comienzo, pero también quiero aceptar caracteres Unicode que se pueden mostrar de una manera normal.


Hay algunas respuestas razonables aquí, pero en mi caso quiero tomar algo que es una cadena que podría tener espacios y puntuación y, en lugar de simplemente eliminarlos, preferiría reemplazarlos por un guión bajo. Aunque los espacios son un carácter de nombre de archivo permitido en la mayoría de los sistemas operativos, son problemáticos. Además, en mi caso, si la cadena original contenía un período en el que no quería que pasara al nombre del archivo, o generaría "extensiones adicionales" que podría no querer (yo mismo estoy agregando la extensión)

def make_safe_filename(s): def safe_char(c): if c.isalnum(): return c else: return "_" return "".join(safe_char(c) for c in s).rstrip("_") print(make_safe_filename( "hello you crazy $#^#& 2579 people!!! : die!!!" ) + ".gif")

huellas dactilares:

hello_you_crazy _______ 2579_personas ______ die ___. gif


Más o menos lo que se ha mencionado aquí con regexp, pero a la inversa (reemplace cualquiera NO listado en la lista):

>>> import re >>> filename = u"ad/nbla''{-+/)(ç1?" >>> re.sub(r''[^/w/d-]'',''_'',filename) u''ad_bla__-_____1_''


Mis requisitos eran conservadores (los nombres de archivo generados debían ser válidos en múltiples sistemas operativos, incluidos algunos sistemas operativos móviles antiguos). Terminé con:

"".join([c for c in text if re.match(r''/w'', c)])

Ese blanco enumera los caracteres alfanuméricos (az, AZ, 0-9) y el guión bajo. La expresión regular puede compilarse y almacenarse en caché por eficiencia, si hay muchas cadenas que coincidan. Para mi caso, no habría hecho ninguna diferencia significativa.


No hay soluciones aquí, solo problemas que debes considerar:

  • ¿Cuál es su longitud máxima mínima de nombre de archivo? (p. ej., DOS admite solo 8-11 caracteres; la mayoría del sistema operativo no admite> 256 caracteres)

  • ¿Qué nombres de archivo están prohibidos en algún contexto? (Windows todavía no admite guardar un archivo como CON.TXT ; consulte https://blogs.msdn.microsoft.com/oldnewthing/20031022-00/?p=42073 )

  • recuerda eso y .. tienen significados específicos (directorio actual / padre) y, por lo tanto, no son seguros.

  • ¿Existe el riesgo de que los nombres de archivo colisionen, ya sea por la eliminación de caracteres o por el mismo nombre de archivo que se usa varias veces?

¿Considerar solo el hashing de los datos y usar el volcado hexadecimal de eso como un nombre de archivo?


Pitón:

"".join([c for c in filename if c.isalpha() or c.isdigit() or c=='' '']).rstrip()

esto acepta caracteres Unicode pero elimina saltos de línea, etc.

ejemplo:

filename = u"ad/nbla''{-+/)(ç?"

da: adblaç

edit str.isalnum () hace alfanumérico en un paso. - comentario de queueoverflow abajo. danodonovan insinuó en mantener un punto incluido.

keepcharacters = ('' '',''.'',''_'') "".join(c for c in filename if c.isalnum() or c in keepcharacters).rstrip()


Pitón:

for c in r''[]//;,><&*:%=+@!#^()|?^'': filename = filename.replace(c,'''')

(solo un ejemplo de los caracteres que querrá eliminar) La r delante de la cadena se asegura de que la cadena se interprete en su formato original, lo que le permite eliminar la barra invertida también.

Edición: solución de expresiones regulares en Python:

import re re.sub(r''[]//;,><&*:%=+@!#^()|?^'', '''', filename)