2009-04-16 28 views
31

Estoy intentando crear una expresión regular que detectará cualquier carácter que Windows no acepte como parte de un nombre de archivo (¿son los mismos para otros sistemas operativos? No lo sé, para ser honesto).Regex para reemplazar caracteres que Windows no acepta en un nombre de archivo

Estos símbolos son:

 \/: * ? " |

De todos modos, esto es lo que tengo: [\\/:*?\"<>|]

El probador encima en http://gskinner.com/RegExr/ muestra que esto es trabajando. Para la cadena Allo*ha, el símbolo * se ilumina, lo que indica que se ha encontrado. Si ingreso Allo**ha, solo se encenderá el primer *. Así que creo que necesito modificar esta expresión regular para encontrar todas las apariencias de los personajes mencionados, pero no estoy seguro.

Como ves, en Java, tengo la suerte de tener la función String.replaceAll(String regex, String replacement). La descripción dice:

Reemplaza cada subcadena de esta cadena que coincide con la expresión regular dada con el reemplazo dado.

En otras palabras, incluso si la expresión regular solo encuentra la primera y luego deja de buscar, esta función aún las encontrará todas.

Por ejemplo: String.replaceAll("[\\/:*?\"<>|]","")

Sin embargo, no me siento que puedo correr ese riesgo. Entonces, ¿alguien sabe cómo puedo extender esto?

+0

-1 hacer de esto una qeustion y decirnos el idioma o contexto que está utilizando y que voy a dar su voto hacia atrás – ojblass

+0

También me gustaría saber qué idioma tu uso – Kredns

+3

Tenga en cuenta que, debido a que su expresión regular tiene la forma de un literal de cadena de Java, tiene que hacer doble escape de las barras diagonales inversas: "[\\\\:"? \ "<> |]". La forma en que lo tenía, simplemente estaba escapando de la barra inclinada (lo cual no es necesario, pero tampoco es un error). –

Respuesta

14

reglas de nombre de archivo de Windows son complicado. Solo estás rascando la superficie.

Por ejemplo aquí hay algunas cosas que no son válidos los nombres de archivo, además de los chracters se enumeran a continuación:

        (yes, that's an empty string) 
. 
.a 
a. 
a         (that's a leading space) 
a         (or a trailing space) 
com 
prn.txt 
[anything over 240 characters] 
[any control characters] 
[any non-ASCII chracters that don't fit in the system codepage, 
if the filesystem is FAT32] 

Extracción de caracteres especiales en un solo sub expresiones regulares como String.replaceAll() no es suficiente; puede terminar fácilmente con algo no válido como una cadena vacía o un final "." o "". Reemplazar algo como "[^ A-Za-z0-9 _.] *" Con '_' sería un mejor primer paso. Pero aún necesitará un procesamiento de mayor nivel en la plataforma que esté utilizando.

+0

Las reglas de nombres de archivo de Windows son de hecho complicadas. Nadie (ni siquiera Microsoft) ha escrito un conjunto de reglas totalmente correctas. Yo tampoco. Pero puedo decirte ". es legal (ese directorio siempre existe), y ".a" y "a". y com y> 240 caracteres, etc. se pueden crear escapando los nombres perfectamente legalmente. –

+0

¡Bien '.' (Y '..') son una ruta de acceso legal, pero no se puede usar como nombre de archivo, obviamente! ¿Cómo se 'escapan' los puntos iniciales/finales y los nombres de archivo reservados? No puedo ver ninguna interfaz pública que lo permita; tanto la interfaz de usuario como la interfaz IO del archivo renombran los puntos y no permiten el nombre reservado. – bobince

+0

(Puedo crear nombres de ruta largos cambiando el nombre y moviéndolos, pero hace que el Explorador y muchas otras aplicaciones sean inestables al acceder a ellos, por lo que es indeseable). – bobince

0

Puede tratar de permitir solo las cosas que desea que el usuario pueda ingresar, por ejemplo, A-Z, a-z y 0-9.

+1

No olvides el período solitario. –

+1

O la amplia gama de caracteres Unicode y extendidos válidos que utilizan personas de todo el mundo. – McDowell

2

Para el registro, los sistemas compatibles con POSIX (incluyendo UNIX y Linux) soportan todos los caracteres excepto el carácter nulo ('\0') y hacia delante diagonal ('/') en los nombres de archivo. Los caracteres especiales como espacio y asterisco se deben escapar en la línea de comandos para que no cumplan sus roles habituales.

0

No puede hacer esto con una sola expresión regular, porque una expresión regular siempre coincide con una subcadena si la entrada. Considere la palabra Alo*h*a, no hay ninguna subcadena que contenga todos los * s, y ningún otro carácter. Entonces, si puede usar la función replaceAll, simplemente quédese con ella.

BTW, el conjunto de caracteres prohibidos es diferente en otros sistemas operativos.

+0

No estoy seguro de entender lo que dice, pero definitivamente puede asociar nombres de archivo no válidos con una expresión regular. – wilhelmtell

+0

Sí, pero no puede desinfectar los nombres de archivo inválidos reemplazando una sola ocurrencia de una expresión regular sin muchos daños colaterales – jpalecek

1

Java tiene una función replaceAll, pero cada lenguaje de programación tiene una manera de hacer algo similar. Perl, por ejemplo, usa el interruptor g para significar un reemplazo global. La función sub de Python le permite especificar la cantidad de reemplazos que se deben realizar. Si, por alguna razón, su idioma no hizo tiene un equivalente, siempre se puede hacer algo como esto:

while (filename.matches(bad_characters) 
    filename.replace(bad_characters, "") 
16

ya que no hubo respuesta, lo hice yo mismo. espero que esta ayuda;)

public static boolean validateFileName(String fileName) { 
    return fileName.matches("^[^.\\\\/:*?\"<>|]?[^\\\\/:*?\"<>|]*") 
    && getValidFileName(fileName).length()>0; 
} 

public static String getValidFileName(String fileName) { 
    String newFileName = fileName.replaceAll("^[.\\\\/:*?\"<>|]?[\\\\/:*?\"<>|]*", ""); 
    if(newFileName.length()==0) 
     throw new IllegalStateException(
       "File Name " + fileName + " results in a empty fileName!"); 
    return newFileName; 
} 
+4

Esto no elimina todos los caracteres no válidos. Olvidaste a los personajes especiales, por ejemplo. –

+1

¿No^impide que coincidan los caracteres especiales, excepto al comienzo del nombre del archivo? Usé fileName.replace ("^ \\. +", "") .replaceAll ("[\\\\: /? *? \" <> |] "," ") –

+0

Si intentas usar cualquier otro reemplazo carácter, entonces "" la expresión regular en la respuesta fallará. La Regex de Oliver Bock funciona bien. – Markus

1

puedo extraer todos los caracteres de texto y los espacios en blanco de la cadena original y también asegurarse de que carácter espacio en blanco no está presente en el extremo de la cadena. Aquí está mi fragmento de código en java.

temp_string = original.replaceAll("[^\\w|\\s]", ""); 
final_string = temp_string.replaceAll("\\s$", ""); 

Creo que ayudé a alguien.

2

Uso la expresión regular pura y simple. Doy caracteres que pueden aparecer y, a través de la negación de "^", cambio todos los demás como un signo de eso. "_"

Cadena fileName = someString.replaceAll ("[^ a-zA-Z0-9 \\. \\ -]", "_");

Por ejemplo: Si no desea estar en la expresión de un "" luego, elimina el "\\".

Cadena fileName = someString.replaceAll ("[^ a-zA-Z0-9 \\ -]", "_");

-1

Windows tampoco acepta "%" como nombre de archivo.

Si está creando una expresión general que puede afectar a los archivos que eventualmente se moverán a otro sistema operativo, le sugiero que agregue más caracteres que puedan tener problemas con ellos.

Por ejemplo, en Linux (muchas distribuciones que conozco), algunos usuarios pueden tener problemas con los archivos que contienen [b] &! ] [/ -() [/ b]. Los símbolos están permitidos en los nombres de archivo, pero es posible que deban ser tratados especialmente por los usuarios y algunos programas tienen errores causados ​​por su existencia.

+0

% en un nombre de archivo funciona para mí en Windows 7. – rhens

0

me hizo muy método simple que funciona para mí para los casos más comunes:

// replace special characters that windows doesn't accept 
private String replaceSpecialCharacters(String string) { 
    return string.replaceAll("[\\*/\\\\!\\|:?<>]", "_") 
      .replaceAll("(%22)", "_"); 
} 

% 22 está codificado si tiene qoute (") en los nombres de archivo.

0

La requerido regex/sintaxis (JS):

.trim().replace(/[\\/:*?\"<>|]/g,"").substring(0,240); 

donde el último bit es opcional, utilícelo solo cuando desee limitar la longitud a 240.otros

funciones útiles (JS):

.toUppperCase(); 
.toLowerCase(); 
.replace(/ /g,' ');  //normalising multiple spaces to one, add before substring. 
.includes("str");  //check if a string segment is included in the filename 
.split(".").slice(-1); //get extension, given the entire filename contains a . 
Cuestiones relacionadas