“This is the sixth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

Path is a very common module in Node. It is used to handle various file path operations. The PATH API can display the corresponding behavior according to the platform, masking the differences between Win and * NIx systems. In this article, read the source code below path for easy comprehension.

Path-related methods

Common APIS and functions of PATH are as follows:

  • path.basename(path[, ext])
  • path.delimiter
  • path.dirname(path)
  • path.extname(path)
  • path.format(pathObject)
  • path.isAbsolute(path)
  • Path. The join (paths […])
  • path.normalize(path)
  • path.parse(path)
  • path.posix
  • path.relative(from, to)
  • Path. The resolve (paths […])
  • path.sep
  • path.toNamespacedPath(path)
  • path.win32

There are specific function links inside, the following analysis of the source code will be explained one by one, this part will not repeat.

Read the path API source code

The last line of path source code is as follows. The exported content is the content introduced when we require. Here, the process module is used to identify whether the current operating system is Win32, and different content is exported according to the operating system. Process is also a module provided by Node, which must be handled internally by calling the native API. We will read about this later, so we won’t go into details here.

Win32 is a Windows environment. Posix is a threading standard (see Wiki). It was first used by Unix systems, and later by UNIX-like systems. Windows is now compatible, but it is often used as a proxy for NIX systems. Specific platform differences between the two will be compared and analyzed under specific apis.

module.exports = process.platform === 'win32' ? win32 : posix;
Copy the code

After looking at win32 and POSIX two objects, in fact, very simple, there are only some attributes and methods, these are exposed path related API, we can use the path point call in the program, the above has been listed one by one, the following one by one analysis. (Because the order of the document is in accordance with the alphabet, here for the corresponding down, the specific position in the source can be searched and viewed)

path.basename(path[, ext])

This method is used to get the last part of path, similar to the Unix basename command. The second argument is the extension, and if passed it returns the result with the extension removed. To quote the official example directly:

path.basename('/foo/bar/baz/asdf/quux.html'); // Return: 'quux.html'
path.basename('/foo/bar/baz/asdf/quux.html'.'.html'); // return: 'quux'
Copy the code

In fact, the two ends of the implementation is not very different, first look at the POSIX platform logic, and finally look at the differences.

If you think about the logic of this method, match the last delimiter (the/symbol on POSIX), truncate what follows, truncate the extension if it is passed in, and return the final result.

The entry method first validates the argument with a validateString and throws an error if it is passed something other than a string. The extension length should be smaller than the path length; otherwise, it will be considered invalid and treated as no extension. The path is traversed from back to front and the code is obtained through charCodeAt to determine whether it is a delimiter (/ on POSIX platform). The result is returned by intercepting the content that starts at the position next to where the delimiter was first matched and ends at the position before the extension. In cases where no extension is passed in, simply intercept to the end.

A Windows system can have multiple disk partitions. In the case that the path starts from the root directory, the path is preceded by a drive letter, such as C:. In this case, you need to exclude the first two characters and start processing from the third character. In addition, Windows separator for/or \ both can be, so here need to judge the two cases, in the source isPathSeparator method to handle win32 separator.

In particular, in many programming languages such as JS, ‘ ‘is an escape character, so to represent the \ character itself, you need to write \.

path.delimiter

This is a constant that returns the path delimiter of the corresponding operating system. The path delimiter is a symbol used to separate multiple paths written side by side. A common scenario is when setting environment variables. On POSIX, it is:. In the source code, that is, two exported property value constants.

In the program, we can use:

// posix

console.log(process.env.PATH);
/ / print: '/ usr/bin: / bin: / usr/sbin, / sbin, / usr/local/bin'

process.env.PATH.split(path.delimiter);
/ / return: ['/usr/bin ', '/ bin', '/ usr/sbin', '/ sbin', '/ usr/local/bin']

// win32

console.log(process.env.PATH);
// Print: 'C:\Windows\system32; C:\Windows; C:\Program Files\node\'

process.env.PATH.split(path.delimiter);
/ / return: [' C: \ \ Windows \ \ system32 ', 'C: \ \ Windows',' C: \ \ Program Files \ \ node \ \ ']
Copy the code

path.dirname(path)

This method is used to get the directory name of path, similar to the Unix dirname command, as in:

path.dirname('/foo/bar/baz/asdf/quux'); // Returns: '/foo/bar/baz/asdf'
Copy the code

This approach is implemented quite differently on Win32 and POSIX, starting with the simpler POSIX platform.

Posix platform implementation is very simple, still from back to front, find the first delimiter to intercept the previous content, in particular, for the case of no match, absolute path return/relative path return.

In Win32 platform, the core processing logic is the same as POSIX, but there is a special logic about the related processing of drive letters at the beginning, and the correct dirname is finally intercepted through multiple traversal processing.

path.extname(path)

Returns the extension, including. Symbol, here is a string match, find the last occurrence. Intercept the position of the following content if. Returns null if it appears at the top of the file.

path.extname('index.html'); // Return: '.html'

path.extname('index.coffee.md'); // return: '.md'

path.extname('index.'); // return: '.'

path.extname('index'); // return:"

path.extname('.index'); // return:"

path.extname('.index.md'); // return: '.md'
Copy the code

Specific matching ideas are not what special, is still from the back forward traversal, Win32 under the need to deal with the first drive letter information.

path.isAbsolute(path)

On POSIX, it is easy to determine whether the path starts with a slash (/). On Win32, it is more complicated. The path that starts with a drive letter meets the absolute path condition.

// posix path.isAbsolute('/foo/bar'); // true path.isAbsolute('/baz/.. '); // true path.isAbsolute('qux/'); // false path.isAbsolute('.'); // false // win32 path.isAbsolute('//server'); // true path.isAbsolute('\\\\server'); // true path.isAbsolute('C:/foo/.. '); // true path.isAbsolute('C:\\foo\\.. '); // true path.isAbsolute('bar\\baz'); // false path.isAbsolute('bar/baz'); // false path.isAbsolute('.'); // falseCopy the code

path.posix

Returns the POSIX part of the PATH method. At the end of the source code there are two lines:

posix.win32 = win32.win32 = win32;
posix.posix = win32.posix = posix;
Copy the code

Win32 and POSIX object references are mounted on the exported content. No matter what platform you are on, you can obtain the desired object through path, through which you can access properties and methods of the corresponding platform.

path.sep

A constant, the system separator property, is returned in Win32, and on POSIX it returns’/’. In fact, Win32 supports both, but here it only returns, also because of the escape character, the source code is \. Common usage:

// posix 'foo/bar/baz'.split(path.sep); / / return: [' foo ', 'bar', 'baz'] / / win32 'foo \ \ bar \ \ baz' split (path. Sep); // Return: ['foo', 'bar', 'baz']Copy the code

path.toNamespacedPath(path)

This method only works in Win32, posiX is an empty method and returns path directly. See this link for more information on namespace, which I haven’t used, and the source code just matches the path based on the format.

path.win32

See the path. The posix.

Here are some simple functions under PATH. Reading the source code can help you understand the underlying logic, and there are other methods under Path that you may want to explore more deeply.