8

Using JAVA. I am trying to find a more elegant way for validating a Linux folder path (not including the file name).

What I have so far is this: "^\\/$|^((\\/([a-zA-Z0-9_-]+))+)$"

Folder paths should include only following characters: letters, numbers, dashes or underscore.

Test cases

Valid/ matches:

  • /
  • /abc
  • /abc/abc/abc/abc

Invalid / not-matches:

  • null or empty string
  • /abc/
  • /abc/abc/abc/abc/
hc_dev
  • 8,389
  • 1
  • 26
  • 38
afrey
  • 141
  • 1
  • 2
  • 13
  • Well the elegant way would be to not use regex at all and instead use the nio libraries to determine if the path is valid.... – Roddy of the Frozen Peas Mar 08 '19 at 20:14
  • What is the use-case for your validation? Why is your RegEx not working for you? Maybe we can find a better solution besides using the RegEx :) – hc_dev Mar 08 '19 at 21:15
  • My pattern works, it just looks clunky, and wasn't sure I was doing it right. – afrey Mar 08 '19 at 21:26
  • Why are you limiting the folder names to alphanumeric? A folder name can contain close to any character. – Toto Mar 09 '19 at 10:28
  • Using only alphanumeric because of requirements in the application we are using. – afrey Mar 10 '19 at 13:07

3 Answers3

7

Issue with your RegEx

Your supplied RegEx is working on the test-cases.

You could even reduce it by removing backslashes \\ and outer pair of parentheses. Begin ^ and end $ are only needed once (around the two alternatives).

Possible Solution using Regular Expression

You can test the RegEx on RegexPlanet.com (click on Java-Button for tests)

^/|(/[a-zA-Z0-9_-]+)+$

or equivalent (see demo on RegexPlanet)

^/|(/[\w-]+)+$

Explained: \w matches a word-character (same as [a-zA-Z0-9_], not matching the dash).

Implementation in Java code:

public boolean isValidLinuxDirectory(String path) {
    Pattern linuxDirectoryPattern = Pattern.compile("^/|(/[a-zA-Z0-9_-]+)+$");
     return path != null && !path.trim().isEmpty() && linuxDirectoryPattern.matcher( path ).matches();
}

Alternative Solution using File

Note the docs on isDirectory():

Returns: true if and only if the file denoted by this abstract pathname exists and is a directory; false otherwise

So it may only validate your requirements (valid Linux folder) if run on a Linux machine and if the folder/directory exists.

public boolean isValidExistingDirectory(String path) {
     if (path == null || path.trim().isEmpty()) return false;
     File file = new File( path );
     return file.isDirectory();
}

Extended Solution

As stated in comment the special form of root // should also be valid. Then use this RegEx:

^/|//|(/[\w-]+)+$

It supports:

  1. root-directory /
  2. special form of root-directory //
  3. any non-root directory, which name is composed out of alphas, numbers, dash or underscore (e.g. /abc/123/_abc-123)

See also

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • Thanks a bunch! Very helpful! – afrey Mar 10 '19 at 13:05
  • `^/|/[a-zA-Z0-9_-]+)+$` does not work for the case where the folder path is `//`. `^/$|^(/[a-zA-Z0-9_-]+)+$` works. – afrey Mar 10 '19 at 14:43
  • @afrey OK. Then please **UPDATE** your question for extended requirement (as I just did). Sure that your regex `^/$|^(/[a-zA-Z0-9_-]+)+$` [does match the special-root](https://www.regexplanet.com/share/index.html?share=yyyyut9ufyr) (`//`) ?? – hc_dev Mar 11 '19 at 11:10
1

Here ya go: \/[a-zA-Z0-9_\/-]*[^\/]$

EDIT

First character matches a forward slash /. The following character group matches a-z, A-Z, 0-9, underscores, forward slashes, and dashes (all accepted directory and filename characters). The following asterisk makes the pattern match that character group 0 or more times (so any combo of those characters). The last character group has a negation ^ meaning it matches anything EXCEPT what's in the character group, being the final forward slash that we don't want to match. Finally the $ to end the string.

Logan Rodie
  • 673
  • 4
  • 12
  • Also if you can actually use the filesystem take a look at [this](https://stackoverflow.com/questions/468789/is-there-a-way-in-java-to-determine-if-a-path-is-valid-without-attempting-to-cre) – Logan Rodie Mar 08 '19 at 19:47
  • Great, but it doesn't accept "/" as a path. Here's an improvment: `^\/([a-zA-Z0-9_\/-]*[^\/])?$` – Jaumzera Jul 25 '22 at 15:09
0

To cover all cases including the root directory, you will need the following:

^\/$|(\/[a-zA-Z_0-9-]+)+$

See Regex Demo using global and multiline modifiers.

AdminOfThings
  • 23,946
  • 4
  • 17
  • 27