Muhammad Imran Tariq
Muhammad Imran Tariq

Reputation: 23352

File path validation in javascript

I am trying to validate XML file path in javascript. My REGEX is:

var isValid = /^([a-zA-Z]:)?(\\{2}|\/)?([a-zA-Z0-9\\s_@-^!#$%&+={}\[\]]+(\\{2}|\/)?)+(\.xml+)?$/.test(str);

It returns true even when path is wrong. These are valid paths

D:/test.xml
D:\\folder\\test.xml
D:/folder/test.xml
D:\\folder/test.xml
D:\\test.xml

Upvotes: 4

Views: 32596

Answers (3)

Ravi K Thapliyal
Ravi K Thapliyal

Reputation: 51711

Tested using Scratchpad.

var regex = /^[a-z]:((\/|(\\?))[\w .]+)+\.xml$/i;

Prints true in Web Console: (Ctrl+Shift+K on Firefox)

console.log(regex.test("D:/test.xml"));
console.log(regex.test("D:\\folder\\test.xml"));
console.log(regex.test("D:/folder/test.xml"));
console.log(regex.test("D:\\folder/test.xml"));
console.log(regex.test("D:\\test.xml"));
console.log(regex.test("D:\\te st_1.3.xml")); // spaces, dots allowed

Or, using Alert boxes:

alert(regex.test("D:/test.xml"));
alert(regex.test("D:\\folder\\test.xml"));
alert(regex.test("D:/folder/test.xml"));
alert(regex.test("D:\\folder/test.xml"));
alert(regex.test("D:\\test.xml"));
alert(regex.test("D:\\te st_1.3.xml"));

Invalid file paths:

alert(regex.test("AD:/test.xml")); // invalid drive letter
alert(regex.test("D:\\\folder\\test.xml")); // three backslashes
alert(regex.test("/folder/test.xml")); // drive letter missing
alert(regex.test("D:\\folder/test.xmlfile")); // invalid extension

Upvotes: 0

t.niese
t.niese

Reputation: 40842

At first the obvious errors:

+ is a repeat indicator that has the meaning at least one.
so the (\.xml+) will match everything starting with .xm followed by one or more l (it would also match .xmlllll). the ? means optional, so (\.xml+)? has the meaning it could have an .xml but it is not required.

the same is for ([a-zA-Z]:)? this means the driver letter is optional.

Now the not so obvious errors

[a-zA-Z0-9\\s_@-^!#$%&+={}\[\]] here you define a list of allowed chars. you have \\s and i assume you want to allow spaces, but this allows \ and s so you need to change it to \s. then you have this part @-^ i assume you want to allow @, - and ^ but the - has a special meaning inside of [ ] with it you define a range so you allow all chars that are in the range of @ to ^ if you want to allow - you need to escape it there so you have to write @\-^ you also need to take care about ^, if it is right after the [ it would have also a special meaning.

your Regex should contain the following parts:

  • ^[a-z]: start with (^) driver letter
  • ((\\|\/)[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+ followed by one or more path parts that start with either \ or / and having a path name containing one or more of your defined letters (a-z0-9\s_@\-^!#$%&+={}\[\])
  • \.xml$ ends with ($) the .xml

therefore your final regex should look like this
/^[a-z]:((\\|\/)[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+\.xml$/i.test(str)
(under the assumption you do a case insensitve regex using the i flag)

EDIT:

var path1 = "D:/test.xml";               // D:/test.xml
var path2 = "D:\\folder\\test.xml";      // D:\folder\test.xml
var path3 = "D:/folder/test.xml";        // D:/folder/test.xml
var path4 = "D:\\folder/test.xml";       // D:\folder/test.xml
var path5 = "D:\\test.xml";              // D:\test.xml

console.log( /^[a-z]:((\\|\/)[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+\.xml$/i.test(path1) );
console.log( /^[a-z]:((\\|\/)[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+\.xml$/i.test(path2) );
console.log( /^[a-z]:((\\|\/)[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+\.xml$/i.test(path3) );
console.log( /^[a-z]:((\\|\/)[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+\.xml$/i.test(path4) );
console.log( /^[a-z]:((\\|\/)[a-z0-9\s_@\-^!#$%&+={}\[\]]+)+\.xml$/i.test(path5) );

UPDATE:

you need to take care about the / and the \ if you need to escape them depends on if you use it with new RegExp(' ... the regex ... ',"i") and new RegExp(" ... the regex ... ","i") or with / ... the regex ... /i

for further informations about regular expressions you should take a look at e.g. www.regular-expressions.info

Upvotes: 6

Ejaz
Ejaz

Reputation: 8872

This could work out for you

var str = 'D:/test.xml';
var str2 = 'D:\\folder\\test.xml';
var str3 = 'D:/folder/test.xml';
var str4 = 'D:\\folder/test.xml';
var str5 = 'D:\\test\\test\\test\\test.xml';

var regex = new RegExp('^[a-z]:((\\\\|\/)[a-zA-Z0-9_ \-]+)+\.xml$', 'i'); 
regex.test(str5);

The reason of having \\\\ in RegExp to match a \\ in string is that javascript uses \ to escape special characters, i.e., \n for new lines, \b for word boundary etc. So to use a literal \, use \\. It also allows you to have different rules for file name and folder name.

Update

[a-zA-Z0-9_\-]+ this section of regexp actually match file/folder name. So to allow more characters in file/folder name, just add them to this class, e.g., to allow a * in file/folder name make it [a-zA-Z0-9_\-\*]+

Update 2

For adding to the answer, following is an RegExp that adds another check to the validation, i.e., it checks for mixing of / and \\ in the path.

var str6 = 'D:/This is folder/test @ file.xml';
var str7 = 'D:/This is invalid\\path.xml'
var regex2 = new RegExp('^[a-z]:(\/|\\\\)([a-zA-Z0-9_ \-]+\\1)*[a-zA-Z0-9_ @\-]+\.xml?', 'gi');

regex2 will match all paths but str7

Update

My apologies for mistyping a ? instead of $ in regex2. Below is the corrected and intended version

var regex2 = new RegExp('^[a-z]:(\/|\\\\)([a-zA-Z0-9_ \-]+\\1)*[a-zA-Z0-9_ @\-]+\.xml$', 'i');

Upvotes: 0

Related Questions