一半君的总结纸

听话只听一半君

#34 How do I enforce backslashes for Windows filepaths (or forward slashes for Maya)?

Method #1: Use “fromNativePath” and “toNativePath

Note: These are only relevant under Windows.

The “toNativePath” command will take a path using forward slashes (or mixed forward and back slashes) and convert it to use backslashes only.

string $path = "C:/path/file.mel";
// Result: C:/path/file.mel //

toNativePath( $path );
// Result: C:\path\file.mel //

string $path = "C:\\path/file.mel";
// Result: C:\path/file.mel //

toNativePath( $path );
// Result: C:\path\file.mel //

The “fromNativePath” will take a path using backslashes (or mixed back and forward slashes) and convert it to use forward slashes only.

string $path = "C:\\path\\file.mel";
// Result: C:\path\file.mel //

fromNativePath( $path );
// Result: C:/path/file.mel //

string $path = "C:\\path/file.mel";
// Result: C:\path/file.mel //

fromNativePath( $path );
// Result: C:/path/file.mel //

Method #2: Use the “substitute” command

There are a few things to be aware of when using the “substitute” command.

Firstly, “substitute” performs only one substitution. It does not replace all occurances in a string. You’ll need to perform a while() loop to replace all occurances of a substring within a string.

  string $path = "C:/path/file.mel";
  while ( $path != ( $path = `substitute "/" $path "\\"` ) );
  // Result: C:\path\file.mel //

Although converting from forward slashes to backslashes is straightforward, replacing a backslash with a forward slash requires a little trickery. Since the substitute command accepts a regular expression for its first argument you must double-up all backslashes within the match string for the ‘substitute’ command. In other words, if you are substituting the “\” character you must specify “\\\\” as your source character. Each “\\” pair is ESCaped by the expression parser first, converting “\\\\” to “\\“, and then this string is passed to the ‘substitute’ command which again ESCapes the pair to a single backslash. This applies to the source string only for the substitution; the destination string requires only a single ESCed backslash to obtain the expected results. A bit weird, yes.

// Maya doesn't like it this way.
while ( $path != ( $path = `substitute "\\" $path "/"` ) );

This attempt results in an error:

// Error: line 1: Invalid escape sequence: Missing character after last backslash "\" in string "\". //

(Or, if you’re running a version prior to v2.5, Maya will crash and burn!)

// Doubling each backslash in the first argument is required.
string $path = "C:\\path\\file.mel";
while ( $path != ( $path = `substitute "\\\\" $path "/"` ) );
// Result: C:/path/file.mel //

Furthermore, if you are replacing a backslash with two backslashes (to ESCape the string for a callback argument, for instance) you must first replace the character with a placeholder, and then replace all placeholders with the doubled character. Otherwise the while() loop would be infinite, finding more and more backslashes to replace.

// First replace all backslashes with asterisk.
while ( $path != ( $path = `substitute "\\\\" $path "*"` ) );
// Result: C:*path*file.mel //

// Now replace all asterisk with double-backslash.
// Note: Asterisk must be ESCed here.
while ( $path != ( $path = `substitute "\\*" $path "\\\\"` ) );
// Result: C:\\path\\file.mel //

Note that the “\\*” argument is a “double-ESCape” of the asterisk, just like what is required for a backslash. The second “\\\\” argument is the typical way you would specify two backslashes – each ESCaped once.

Method #3: Use the ‘tokenize’ command

This method can prove to be more flexible because you have control over how the path is rebuilt; e.g. whether it has a trailing slash or whether it is a relative or absolute path.

Here’s the utility procedure I use to convert a path to Windows slashes.

proc string slash( string $path )
// Input: Directory path with '/' or '\' slash delimiters.
// Output: Directory path with '\' slash delimiters.
{
  string $slash = "";

  string $tokens[];
  int $numTokens = `tokenize $path "\\/" $tokens`;
  int $i;

  $slash = $tokens[0];

  for ( $i = 1; $i < $numTokens; $i++ )
  {
    $slash += ( "\\" + $tokens[$i] );
  }

  return $slash;
}

Example:

  string $path = "C:/path/file.mel";
  $path = slash($path);
  // Result: C:\path\file.mel //

Other Examples

slash2.mel

Same as slash.mel with an additional ‘$isDir’ parameter that allows an extra post-fixed slash if the supplied path specifies a directory.

doubleslash.mel

Converts any backslashes “\” in string to ESC’d backslash “\\” for use when the resultant filepath must be interpreted by an ‘eval’ statement, expression, or the like.

Related How-To’s

13 January 2002

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: