18

So for example say I had it so that all of my files will be transferred from a windows machine to a unix machine as such: C:\test\myFile.txt to {somewhere}/test/myFile.txt (drive letter is irrelevant at this point).

Currently, our utility library that we wrote ourselves provides a method that does a simple replace of all back slashes with forward slashes:

public String normalizePath(String path) {
   return path.replaceAll("\\", "/");
}

Slashes are reserved and cannot be part of a file name, so the directory structure should be preserved. However, I'm not sure if there are other complications between windows and unix paths that I may need to worry about (eg: non-ascii names, etc)

13
  • 6
    Just watch out for spaces -- putting spaces in windows folder names is much more common than in unix directory names. In particular, "\Program Files" gets me all the time. Depending on how you're using the paths, you might have to escape spaces with "\ ".
    – sea-rob
    Commented Jun 16, 2014 at 16:55
  • 1
    @delnan for simplicity, let's limit the scope of the paths to exclude variable paths.
    – MxLDevs
    Commented Jun 16, 2014 at 16:59
  • 2
    @MxyL The problem doesn't go away when you hard-code the path instead of using an environment variable. If you just want a path that doesn't blow up, you should be fine. If you want a meaningful path, or if you want to interact with other software (or user expectations...) you need per-path judgement calls.
    – user7043
    Commented Jun 16, 2014 at 17:09
  • 1
    @delnan I am mainly focused on producing a valid path, but that's a good point. The paths I am converting should be simple enough that they are meaningful by themselves.
    – MxLDevs
    Commented Jun 16, 2014 at 17:56
  • 3
    Backslashes are allowed in filenames on Linux, so replacing backslashes in a Linux path could add invalid directories. For example, /foo\\bar isn't equivalent to /foo/bar on Linux.
    – user76704
    Commented Jun 24, 2014 at 20:27

5 Answers 5

11

Yes, if you only do the replacement on Windows, and turn it off when running on other systems.

Doing the replacement on Unix-like systems is wrong because \ is a valid character in a file or directory name on Unix-like platforms. On these platforms, only NUL and / are forbidden in file and directory names.

Also, some Windows API functions (mostly the lower level ones) do not allow the use of forward slashes ― backslashes must be used with them.

Edit: It turns out that there are some special file systems on Windows on which / and NUL are valid characters, such as the Registry (available at \\?\GLOBALROOT\Registry from a Windows API perspective, or \Registry from the Native API perspective). In the Named Pipe File System (usually mounted at \??\pipe), all characters (including /, \, and even NUL) are valid. So in general, not only is it not valid to replace / with \ on Windows, it is not valid to assume that every Windows file can be accessed using the Windows API! To reliably access arbitrary files, one must use the Native API (NtCreateFile and friends). NtCreateFile also exposes an equivalent of openat(2), which isn’t exposed via the Windows API.

5

Yes, but this whole thing is a moot point. Java seamlessly converts forward slashes to back slashes on Windows. You can simply use forward slashes for all paths that are hard-coded or stored in configuration and it will work for both platforms.

Personally, I always use the forward slash even on Windows because it is not the escape character. Whether the raw path is in code or externalized in a properties file, I encode it the same way.

Try it! This will work in Windows. Obviously, change the actual path to something that exists and your user has permission to read.

File f = new File("c:/some/path/file.txt");
if (!f.canRead()) {
  System.out.println("Uh oh, Snowman was wrong!");
}

Bonus: you can even mix slashes in the same path!

File f = new File("c:/some\\path/file.txt");
if (!f.canRead()) {
  System.out.println("Uh oh, Snowman was wrong again!");
}
5
  • 2
    If you read my entire answer, you would see where I say that always using the Unix file separator will work correctly in both places, no conversion needed.
    – user22815
    Commented Aug 22, 2014 at 1:39
  • The question states that the files will be transferred, and leaves open how the file names are stored. I added a comment to the question asking for clarification on that point. Based on the response, I will edit my answer as appropriate.
    – user22815
    Commented Aug 22, 2014 at 1:45
  • It's quite unlikely that the program actually contains within it a manually entered list of all the files being transferred. It's vastly more likely that some automated mechanism is being used to enumerate the files. Given the problem's parameters as they are stated in the question, this mechanism delivers traditional Windows-style paths. In its current form, this answer is telling the OP to solve a different problem instead without telling them how or even that they should transform theirs into the different problem. Commented Aug 22, 2014 at 1:48
  • I've read the (now edited) version of your previous comment. Consulting the OP as you've now done sounds good. Thanks for your attention to this issue. Commented Aug 22, 2014 at 1:50
  • 3
    Windows recognizes both fowrard and backslashes, and has been that way since early MS-DOS. I.e. every Microsoft OS kernel has had forward slash separator support. Early COMMAND.COM interpreters had a run-time preference: you could configure which slash the interpreter would use for printing and parsing.
    – Kaz
    Commented Jul 8, 2016 at 3:10
5

Another complication on Windows is that it also supports UNC notation as well as the traditional drive letters.

A file on a remote file server can be accessed as \\server\sharename\path\filename.

1
  • 1
    I think this is the only concern quoted so far that is actually a problem for this application. If there are UNC paths involved, they cannot be converted usefully into a Unix-style path.
    – Jules
    Commented Jul 8, 2016 at 7:19
2

No. There are far more things to think about than just the path separator (the "\ vs /" thing). As Rob Y mentions, there is how spaces are handled, and their high frequency in Windows usage. There are different illegal characters in the two environments. There is Unix's willingness to allow almost anything when escaped by a leading "\". There is Windows use of '"' to deal with embedded spaces. There is Windows' use of UCS-16 and Unix's use of ASCII or UTF-8.

etc., etc., etc.

But, for lots of applications that can put constraints on the pathnames they need to manipulate, you actually can do it just the way you suggest. And it will work in at least a large number of the cases, just not all of them.

1
  • 2
    I don't think these concerns are valid for the question as posed The space handling is a user interface issue; Unix systems can handle spaces in filenames just as well as Windows can. The Windows illegal characters are a superset of the Unix ones. There can't be any backslashes in the Windows filenames (other than the directory separators which will be converted). Using quotes for embedded spaces is a user interface level concern, not a file handling issue. The conversion code is apparently in Java, so should handle UCS16->UTF8 conversion automatically.
    – Jules
    Commented Jul 8, 2016 at 7:18
1

Every Microsoft operating system, starting with MS-DOS, has understood, at the kernel level, both forward slashes and backslashes.

Therefore, on Windows, you can convert between them freely; both have equal status as reserved separators. In any valid path, you can replace backslashes with slashes and vice versa, without changing its meaning, as far as the kernel is concerned.

In early versions of DOS, Microsoft's command.com interpreter made it a configurable preference which slash was used to display and parse paths. That was eventually removed.

Some user-space programs in Windows such as, oh, the Windows shell (explorer.exe) do not like forward slashes. That's just shoddy programming in those programs.

2
  • 1
    While this is true, I don't believe it's helpful for the OP's question which (AIUI) involved converting existing path names, which would already have included the backslashes in them. It is very useful for writing cross-platform code to realise that you can just use forward slashes and have them work in most contexts, but in this case I don't think it helps.
    – Jules
    Commented Jul 8, 2016 at 7:22
  • 1
    @Jules OP is transferring files from Windows. This answer explains that there are no backslashes to be replaced. They are not in the Windows filesystem itself at all. All the paths are expressible with forward slashes (and Windows even understands it).
    – Kaz
    Commented Jul 8, 2016 at 14:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.