Quiero incluir una funcionalidad de cambio de nombre de archivo por lotes en mi aplicación. Un usuario puede escribir un patrón de nombre de archivo de destino y (después de reemplazar algunos comodines en el patrón) necesito verificar si será un nombre de archivo legal en Windows. Intenté usar expresiones regulares como, [a-zA-Z0-9_]+
pero no incluye muchos caracteres nacionales específicos de varios idiomas (por ejemplo, diéresis, etc.). ¿Cuál es la mejor manera de hacer tal verificación?
c#
windows
file
filesystems
tomash
fuente
fuente
Respuestas:
Puede obtener una lista de caracteres no válidos de
Path.GetInvalidPathChars
yGetInvalidFileNameChars
.UPD: Vea la sugerencia de Steve Cooper sobre cómo usarlos en una expresión regular.
UPD2: Tenga en cuenta que de acuerdo con la sección Comentarios en MSDN "No se garantiza que la matriz devuelta por este método contenga el conjunto completo de caracteres que no son válidos en los nombres de archivo y directorio". La respuesta proporcionada por sixlettervaliables entra en más detalles.
fuente
Desde "Nombrar un archivo o directorio" de MSDN, estas son las convenciones generales sobre qué es un nombre de archivo legal en Windows:
Puede usar cualquier carácter en la página de códigos actual (Unicode / ANSI superior a 127), excepto:
<
>
:
"
/
\
|
?
*
Algunas cosas opcionales para verificar:
\?\
prefijo)\?\
(tenga en cuenta que el prefijo puede expandir los componentes del directorio y hacer que desborde el límite de 32,000)fuente
Regex unspupportedRegex = new Regex("(^(PRN|AUX|NUL|CON|COM[1-9]|LPT[1-9]|(\\.+)$)(\\..*)?$)|(([\\x00-\\x1f\\\\?*:\";|/<>])+)|(([\\. ]+)", RegexOptions.IgnoreCase);
^(?!^(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)(?:\.*?(?!\.))[^\x00-\x1f\\?*:\";|\/<>]+(?<![\s.])$
Para .Net Frameworks anteriores a 3.5, esto debería funcionar:
La coincidencia de expresiones regulares debería ayudarlo. Aquí hay un fragmento que usa la
System.IO.Path.InvalidPathChars
constante;Para .Net Frameworks después de 3.0, esto debería funcionar:
http://msdn.microsoft.com/en-us/library/system.io.path.getinvalidpathchars(v=vs.90).aspx
La coincidencia de expresiones regulares debería ayudarlo. Aquí hay un fragmento que usa la
System.IO.Path.GetInvalidPathChars()
constante;Una vez que sepa eso, también debe verificar diferentes formatos, por ejemplo,
c:\my\drive
y\\server\share\dir\file.ext
fuente
Intenta usarlo y atrapa el error. El conjunto permitido puede cambiar entre sistemas de archivos o entre diferentes versiones de Windows. En otras palabras, si quieres saber si a Windows le gusta el nombre, dale el nombre y deja que te lo diga.
fuente
Esta clase limpia nombres de archivo y rutas; úsalo como
Aquí está el código;
fuente
Esto es lo que uso:
El primer patrón crea una expresión regular que contiene los nombres y caracteres de archivo no válidos / ilegales solo para plataformas Windows. El segundo hace lo mismo pero asegura que el nombre sea legal para cualquier plataforma.
fuente
@"^(?!(?:PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d)(?:\..+)?$)[^\x00-\x1F\xA5\\?*:\"";|\/<>]+(?<![\s.])$"
Un caso de esquina para tener en cuenta, que me sorprendió cuando lo descubrí por primera vez: ¡Windows permite caracteres de espacio iniciales en los nombres de archivos! Por ejemplo, los siguientes son todos los nombres de archivo legales y distintos en Windows (menos las comillas):
Una conclusión de esto: tenga cuidado al escribir código que recorte los espacios en blanco iniciales / finales de una cadena de nombre de archivo.
fuente
Simplificando la respuesta de Eugene Katz:
O
fuente
Path.GetInvalidFileNameChars
. Eche un vistazo aquí: referencesource.microsoft.com/#mscorlib/system/io/path.cs,289 : para cada carácter de sufileName
, se crea un clon de la matriz.Microsoft Windows: el kernel de Windows prohíbe el uso de caracteres en el rango 1-31 (es decir, 0x01-0x1F) y los caracteres "*: <>? \ |. Aunque NTFS permite que cada componente de ruta (directorio o nombre de archivo) tenga 255 caracteres de longitud y rutas de hasta 32767 caracteres de longitud, el kernel de Windows solo admite rutas de hasta 259 caracteres de longitud. Además, Windows prohíbe el uso de los nombres de dispositivo MS-DOS AUX, CLOCK $, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, CON, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9, NUL y PRN, así como estos nombres con cualquier extensión (por ejemplo, AUX.txt), excepto cuando se usa Rutas UNC largas (por ejemplo, \. \ C: \ nul.txt o \? \ D: \ aux \ con). (De hecho, CLOCK $ puede usarse si se proporciona una extensión). Estas restricciones solo se aplican a Windows: Linux, por ejemplo, permite el uso de "*: <>? \ | incluso en NTFS.
Fuente: http://en.wikipedia.org/wiki/Filename
fuente
En lugar de incluir explícitamente todos los caracteres posibles, puede hacer una expresión regular para verificar la presencia de caracteres ilegales y luego informar un error. Idealmente, su aplicación debería nombrar los archivos exactamente como lo desee el usuario, y solo llorar si encuentra un error.
fuente
La pregunta es si está tratando de determinar si un nombre de ruta es una ruta legal de Windows, o si es legal en el sistema donde se está ejecutando el código.? Creo que esto último es más importante, así que personalmente, probablemente descomponga la ruta completa e intente usar _mkdir para crear el directorio al que pertenece el archivo, luego intente crear el archivo.
De esta manera, usted sabe no solo si la ruta contiene solo caracteres válidos de Windows, sino si realmente representa una ruta que puede ser escrita por este proceso.
fuente
Utilizo esto para deshacerme de caracteres no válidos en los nombres de archivo sin lanzar excepciones:
fuente
Además, CON, PRN, AUX, NUL, COM # y algunos otros nunca son nombres de archivo legales en ningún directorio con ninguna extensión.
fuente
Para complementar las otras respuestas, aquí hay un par de casos adicionales adicionales que es posible que desee considerar.
Excel puede tener problemas si guarda un libro en un archivo cuyo nombre contiene los caracteres '[' o ']'. Ver http://support.microsoft.com/kb/215205 para más detalles.
Sharepoint tiene un conjunto adicional de restricciones adicionales. Consulte http://support.microsoft.com/kb/905231 para más detalles.
fuente
Desde MSDN , aquí hay una lista de caracteres que no están permitidos:
fuente
También el sistema de archivos de destino es importante.
Bajo NTFS, algunos archivos no se pueden crear en directorios específicos. EG $ Arranque en la raíz
fuente
$Boot
ya existe un archivo llamado en el directorio?Esta es una pregunta ya respondida, pero solo por "Otras opciones", aquí hay una no ideal:
(no es ideal porque usar Excepciones como control de flujo es una "mala cosa", generalmente)
fuente
true
.Las expresiones regulares son excesivas para esta situación. Puede usar el
String.IndexOfAny()
método en combinación conPath.GetInvalidPathChars()
yPath.GetInvalidFileNameChars()
.También tenga en cuenta que ambos
Path.GetInvalidXXX()
métodos clonan una matriz interna y devuelven el clon. Entonces, si va a hacer esto mucho (miles y miles de veces), puede almacenar en caché una copia de la matriz de caracteres no válidos para su reutilización.fuente
Si solo está tratando de verificar si una cadena que contiene su nombre / ruta de archivo tiene caracteres no válidos, el método más rápido que he encontrado es usar
Split()
para dividir el nombre del archivo en una matriz de partes donde haya un carácter no válido. Si el resultado es solo una matriz de 1, no hay caracteres no válidos. :-)Intenté ejecutar este y otros métodos mencionados anteriormente en un nombre de archivo / ruta 1,000,000 de veces en LinqPad.
El uso
Split()
es solo ~ 850 ms.El uso
Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]")
es de alrededor de 6 segundos.Las expresiones regulares más complicadas son MUCHO peores, al igual que algunas de las otras opciones, como usar los diversos métodos en la
Path
clase para obtener el nombre del archivo y dejar que su validación interna haga el trabajo (muy probablemente debido a la sobrecarga del manejo de excepciones).De acuerdo, no es muy frecuente que necesite validar 1 millón de nombres de archivo, por lo que una iteración única está bien para la mayoría de estos métodos de todos modos. Pero sigue siendo bastante eficiente y efectivo si solo está buscando caracteres no válidos.
fuente
Muchas de estas respuestas no funcionarán si el nombre de archivo es demasiado largo y se ejecuta en un entorno anterior a Windows 10. Del mismo modo, piense qué desea hacer con los períodos: permitir que el inicio o el final sea técnicamente válido, pero puede crear problemas si no desea que el archivo sea difícil de ver o eliminar, respectivamente.
Este es un atributo de validación que creé para buscar un nombre de archivo válido.
y las pruebas
fuente
Mi intento:
Esto no es perfecto porque
Path.GetInvalidPathChars
no devuelve el conjunto completo de caracteres que no son válidos en los nombres de archivos y directorios y, por supuesto, hay muchas más sutilezas.Entonces uso este método como complemento:
Intenta crear el archivo y devolver falso si hay una excepción. Por supuesto, necesito crear el archivo, pero creo que es la forma más segura de hacerlo. Tenga en cuenta también que no estoy eliminando directorios que se han creado.
También puede usar el primer método para hacer una validación básica y luego manejar cuidadosamente las excepciones cuando se usa la ruta.
fuente
Sugiero simplemente usar Path.GetFullPath ()
fuente
Tengo esta idea de alguien. No sé quién. Deje que el sistema operativo haga el trabajo pesado.
fuente
Este cheque
filtra los nombres con caracteres no válidos (
<>:"/\|?*
y ASCII 0-31), así como dispositivos de DOS (reservadosCON
,NUL
,COMx
). Permite espacios iniciales y nombres de todos los puntos, de acuerdo conPath.GetFullPath
. (La creación de archivos con espacios iniciales tiene éxito en mi sistema).Usé .NET Framework 4.7.1, probado en Windows 7.
fuente
Un revestimiento para verificar caracteres ilegales en la cadena:
fuente
En mi opinión, la única respuesta adecuada a esta pregunta es intentar usar la ruta y dejar que el sistema operativo y el sistema de archivos la validen. De lo contrario, simplemente está reimplementando (y probablemente de manera deficiente) todas las reglas de validación que el sistema operativo y el sistema de archivos ya usan y si esas reglas se cambian en el futuro, tendrá que cambiar su código para que coincida.
fuente
Nombres de archivos de Windows son bastante restrictivo, así que realmente no podría ser incluso que gran parte de un problema. Los caracteres que Windows no permite son:
Podría escribir fácilmente una expresión para verificar si esos caracteres están presentes. Sin embargo, una mejor solución sería tratar de nombrar los archivos como el usuario quiera y alertarlos cuando un nombre de archivo no se pegue.
fuente