3

What's the best way to determine if a character is a valid file path? So CheckFilePath( "my*file.csv") would return FALSE (on windows * is invalid character), whereas CheckFilePath( "c:\\users\\blabla\\desktop\\myfile.csv" ) would return TRUE.

Note that a file path can be valid but not exist on disk.

Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
Suraj
  • 35,905
  • 47
  • 139
  • 250
  • Well, if you can find a Perl Compatible Regular Expression (see `?regexp` that only matches valid Windows paths, you could then do `grepl(regular_exp, filename)` to test for `filename`'s validity. But constructing such a regular expression might be harder than you think. See, e.g., the accepted answer to this SO question http://stackoverflow.com/questions/537772/what-is-the-most-correct-regular-expression-for-a-unix-file-path . – Josh O'Brien Oct 15 '11 at 16:54
  • yup...that's the DIY answer =) was hoping someone had already tackled this – Suraj Oct 15 '11 at 17:00

4 Answers4

4

Perhaps file.exists() is what you're after? From the help page:

file.exists returns a logical vector indicating whether the files named by its argument exist.
(Here ‘exists’ is in the sense of the system's stat call: a file will be reported as existing only
if you have the permissions needed by stat. Existence can also be checked by file.access, which
might use different permissions and so obtain a different result. 

Several other functions to tap into the computers file system are available as well, also referenced on the help page.

Chase
  • 67,710
  • 18
  • 144
  • 161
  • Not quite. This determines if a file exists. I'm looking for valid file path. A file path can be valid but not exist (i.e. you intend to write to the file). Updated the original post to reflect this – Suraj Oct 15 '11 at 16:36
  • Why would CheckFilePath( "&&&(&(&" ) return FALSE? It's a perfectly valid file path. You can make a file with that name. I don't think operating systems have an interface that tests for validity though - normally you'd just try and create it or read it and then get an error. – Spacedman Oct 15 '11 at 16:37
  • Spacedman - I updated original post to an invalid file path on Windows. I'm not sure what's "normal", I think platforms have different ways of dealing with this. In .net you can check for a valid file path before attempting to write the file – Suraj Oct 15 '11 at 16:40
  • Where's the doc for that .Net API call? – Spacedman Oct 15 '11 at 16:44
  • http://stackoverflow.com/questions/422090/in-c-sharp-check-that-filename-is-possibly-valid-not-that-it-exists – Suraj Oct 15 '11 at 16:57
  • Also, just google "check for valid file path in .net". There are several solutions. I can dig-up the one I implimented if that's useful to you. – Suraj Oct 15 '11 at 16:58
3

This is the code that save is using to perform that function:

 ....
 else file(file, "wb")
            on.exit(close(con))
        }
        else if (inherits(file, "connection")) 
            con <- file
        else stop("bad file argument")
 ......
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • cool! I can repurpose this into a function that checks for valid file path. thanks! – Suraj Oct 15 '11 at 17:22
  • ... after checking that it doesn't exist, perhaps? – IRTFM Oct 15 '11 at 17:33
  • that's exactly what I was thinking. Unfortuantely, if it doesn't exist then the file(...) call will create the file, which is not the intention. I don't see any way around this?? – Suraj Oct 15 '11 at 17:36
  • also, if a directory in the path does not exist but in fact the file path is valid then file(...) throws an error. This is a lesser concern and could be called a "feature" of a valid file path checking function – Suraj Oct 15 '11 at 17:38
  • file.exists() would seem to be appropriate for testing. – IRTFM Oct 17 '11 at 19:02
2

I would suggest trying checkPathForOutput function offered by the checkmate package. As stated in the linked documentation, the function:

Check[s] if a file path can be safely be used to create a file and write to it.

Example

checkmate::checkPathForOutput(x = tempfile(pattern = "sample_test_file", fileext = ".tmp"))
# [1] TRUE
checkmate::checkPathForOutput(x = "c:\\users\\blabla\\desktop\\myfile.csv")
# [1] TRUE

Invalid path

\0 character should not be used in Linux1 file names:

checkmate::check_path_for_output("my\0file.csv")
# Error: nul character not allowed (line 1)

1 Not tested on Windows, but looking at the code of checkmate::check_path_for_output indicates that function should work correctly on MS Windows system as well.

Konrad
  • 17,740
  • 16
  • 106
  • 167
1

No, there's no way to do this (reliably). I don't see an operating system interface in neither Windows nor Linux to test this. You would normally try and create the file and get a fail message, or try and read the file and get a 'does not exist' kind of message.

So you should rely on the operating system to let you know if you can do what you want to do to the file (which will usually be read and/or write).

I can't think of a reason other than a quiz ("Enter a valid fully-qualified Windows file path:") to want to know this.

Spacedman
  • 92,590
  • 12
  • 140
  • 224
  • 1
    Thanks. Its good practice to check function parameters upfront and give users friendly error messages when the parameters are malformed. Imagine a function with a filePath parameter that does some file-write operations. Its best to detect an invalid file path and message that to the user, rather than trying to catch/parse an OS message or simply let the user deal with the OS error directly. Most likely the OS error will suck. – Suraj Oct 15 '11 at 16:55
  • Also note that my function might call another function that does the file-writing. That second function might not be writing files directly (i.e. ODBC). best to prevent a error up-front. – Suraj Oct 15 '11 at 17:21
  • I totally disagree. Googling for this in .Net brings up massive debate, solutions that depend on catching exceptions etc etc. If the "solution" you use has any false *positive* cases you'll stop the user creating something they legally can, and hence annoy them. If it has any false *negative* cases you'll still have to cope with the operating system error when you go to read or write the file, which will annoy you. – Spacedman Oct 15 '11 at 21:14
  • We will agree to disagree then =) The solution in .net is not that complicated (its like 5-10 lines of code). It won't allow false positives nor false negatives (that's what your unit tests are for). If you do encounter either, it means your user has tried very hard to break your program (like decompiling?). I don't believe in software that optimizes for solving corner cases. I believe in optimizing for the user experience. The best user-experience and path to least frustration is to help the user avoid errors by detecting errors as far upstream as you can. – Suraj Oct 15 '11 at 22:06
  • Some file paths are only valid on certain file system types, due to length limits or character limitations. Any test on a plain character string isn't going to be with reference to a file system. Does the .net solution need a path and a file system type? – Spacedman Oct 15 '11 at 22:26
  • I'm not sure about the unix/linux world, but in Windows I think the path structure is tied to the OS and not the file system. Checking for valid paths in .net would be difficult cross-platform if the runtime (i.e. CLR) didn't support checking on various non-Windows OS/filesystems. I think it does, but even if not I rarely see .net client-apps actually running cross-platform, so its not a scenario I would optimize for. This whole issue is most difficult with platforms that actually have cross-platform scenarios (like R!). – Suraj Oct 16 '11 at 13:56
  • ...actually, something I've been curious about: if you take away the R developers that are publishing packages on CRAN, what percentage of the remaining developers are using R cross-platform? I'd love to know that stat! – Suraj Oct 16 '11 at 13:59