What's the difference between path.resolve and path.join? - node.js

Is there some difference between the following invocations?
path.join(__dirname, 'app')
vs.
path.resolve(__dirname, 'app')
Which one should be preferred?

The two functions deal with segments starting with / in very different ways; join will just concatenate it with the previous argument, however resolve will treat this as the root directory, and ignore all previous paths - think of it as the result of executing cd with each argument:
path.join('/a', '/b') // Outputs '/a/b'
path.resolve('/a', '/b') // Outputs '/b'
Another thing to note is that path.resolve will always result in an absolute URL, and will use your working directory as a base to resolve this path. But as __dirname is an absolute path anyway this doesn't matter in your case.
As for which one you should use, the answer is: it depends on how you want segments starting in / to behave - should they be simply joined or should they act as the new root?
If the other arguments are hard coded it really doesn't matter, in which case you should probably consider (a) how this line might change in future and (b) how consistent is it with other places in the code.

The default operations of file system path vary based on the operating system we need some thing that abstract it.
The path module provides utilities or API for working with file and directory
paths.
you can include it in your project using
const path = require('path');
The path.join and path.resolve are two different methods of the path module.
Both these methods accept a sequence of paths or path segments.
The path.resolve() method resolves a sequence of paths or path segments into an absolute path.
The path.join() method joins all given path segments together using the platform specific separator as a delimiter, then normalizes the resulting path.
In order to better understand and differentiate behaviours, let me explain it with different scenarios.
1. If we don't supply any arguments to or empty string
in my case, my filename is index.js and the current working directory is E:\MyFolder\Pjtz\node
const path = require('path');
console.log("path.join() : ", path.join());
// outputs .
console.log("path.resolve() : ", path.resolve());
// outputs current directory or equalent to __dirname of the node process
and on running result is as below
λ node index.js
path.join() : .
path.resolve() : E:\MyFolder\Pjtz\node
The inference from above experiment is tha path.resolve() method will output the absolute path where as the path.join() returns . representing the current working directory or relative path if nothing is provided
2. Adding a /path as any of arguments.
const path=require('path');
console.log("path.join() : " ,path.join('abc','/bcd'));
console.log("path.resolve() : ",path.resolve('abc','/bcd'));
and the result is
λ node index.js
path.join() : abc\bcd
path.resolve() : E:\bcd
The inference we can found with this experiment is that path.join() only concatenates the input list with platform specific separator while the path.resolve() process the sequence of paths from right to left, with each subsequent path prepended until an absolute path is constructed.
path.join() concatenates each argument with OS specific separators while path.resolve() will resolve each argument with root and produce output.

1) path.resolve creates the absolute path.
The method creates absoulte path from right to left until an absolute path is constructed.
For example:
path.resolve('/a', 'b', 'c'); // C:\a\b\c
path.resolve('/a', '/b', 'c'); // C:\b\c
path.resolve('/a', '/b', '/c'); // C:\c
If absolute path is not generated, the method using current working directory:
For example:
path.resolve('a', 'b', 'c'); // C:\{current_working_directory}\a\b\c
2) path.join joins all path and the normalize the result
For example:
path.join('/a', '/b', '/c'); // \a\b\c
path.join('/a', '/b', 'c'); // \a\b\c
path.join('/a', 'b', 'c'); // \a\b\c
path.join('a', 'b', 'c'); // a\b\c
EDIT: updated example above suggested by #spmdc

In Simplest` Terms:
path.resolve() just does the following
from left to right-
concatenate the right most parameters with / directly with the root path to make an absolute path (check the examples)
and then concatenates anything without / as a directory
using sergey's example
path.resolve('/a', 'b', 'c'); returns C:\a\b\c
path.resolve('/a', '/b', 'c'); returns C:\b\c
path.resolve('/a', '/b', '/c'); returns C:\c
While join simply concatenates every parameter from left to right whether they have / or not
path.join("/a", "b", "/c", "d") simply returns "\a\b\c\d"

Related

Why do we write dots (.) in path.resolve()?

The code shown below are examples used to explain path.resolve() on https://nodejs.org/api/path.html
path.resolve('/foo/bar', './baz');
// Returns: '/foo/bar/baz'
path.resolve('/foo/bar', '/tmp/file/');
// Returns: '/tmp/file'
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// If the current working directory is /home/myself/node,
// this returns '/home/myself/node/wwwroot/static_files/gif/image.gif'
I noticed that all dots are just omited.
./baz is converted to baz in the first example.
../gif/image.gif is converted to /gif/image.gif in the 3rd example.
Then, why bother writing these dots?
What would happen if these dots didn't exist in the two examples?
Thx!
The path.resolve() method is used to resolve a sequence of path-segments to an absolute path.
It works by processing the sequence of paths from right to left, prepending each of the paths until the absolute path is created. The resulting path is normalized and trailing slashes are removed as required.
If no path segments are given as parameters, then the absolute path of the current working directory is used.
The passed argument is a series of file paths that would be resolved together to form an absolute path.

Node.js path.join() ignoring parameter

According to the documentation:
The path.join() method joins all given path segments together using
the platform-specific separator as a delimiter, then normalizes the
resulting path.
Zero-length path segments are ignored. If the joined path string is a
zero-length string then '.' will be returned, representing the current
working directory.
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// Returns: '/foo/bar/baz/asdf'
path.join('foo', {}, 'bar');
// Throws 'TypeError: Path must be a string. Received {}'
A TypeError is thrown if any of the path segments is not a string.
Am I missing something? Why is:
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// Returns: '/foo/bar/baz/asdf'
Ignoring 'quux' and '..' ?
They're are not zero length?
Even played around in the REPL (see screenshot)
Path.join isn't ignoring the last two parameters. Path.join takes the parameters you input and outputs a normalized path in string format.
So what's actually going on here is that it's constructing your string to form a path left to right, /foo/bar/baz/asdf/quux/, and the last parameter (..) is instructing path.join to 'go back a directory'. So your final result will be: /foo/bar/baz/asdf/
Part 1: what do you expect to happen when you provide an object instead of a string? To cut it short: It doesn’t make sense and hence doesn’t work.
Part 2: since .. means „up one directory“, this clears the last part of the path, hence it seems to not have any effect. Actually, it doesn’t get ignored - it’s just that the last two parameters clear each other.
With regard to path.join('foo', {}, 'bar');, {} represents an empty object, not a string (empty or not). Therefore, it is an invalid parameter for path.join().
With regard to path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');, .. refers to a parent directory.
Through experimentation in a terminal, you will find that...
/foo/bar/baz/asdf/quux/.. is equivalent to /foo/bar/baz/asdf

How do I avoid storing redirections in a boost::filesystem::path?

I'm using Boost::Filesystem to traverse around directories in Linux.
Every time I need to re-define the path to be one directory back, I do something similar to this:
auto p = boost::filesystem::current_path();
p /= "../";
The problem is, that when I output 'p', it will show me the path with "../" still tacked on.
How do I get this evaluated each time I decide to go back a directory. I would like going back a directory to make the path shorter- instead of making the path longer and longer every time.
I thought one of these functions might do it, as they take a path by reference,
boost::filesystem::absolute(...)
boost::filesystem::canonical(...)
but after calling them and re-outputting 'p', the result still shows a "../";
path& make_preferred() does not work either.
canonical or absolute is the way to do it. Do you use the returned path? The given path is taken as a constant reference so it is not modified in place. From the boost manuals:
path canonical(const path& p, const path& base = current_path());
path canonical(const path& p, system::error_code& ec);
path canonical(const path& p, const path& base, system::error_code& ec);
Overview: Converts p, which must exist, to an absolute path that has
no symbolic link, dot, or dot-dot elements.

Difference between path.normalize and path.resolve in Node.js

What is the difference (if any) between path.normalize(your_path) and path.resolve(your_path)?
I know path.resolve(...) can accept multiple arguments, but is the behavior with a single argument the same as calling path.normalize()?
EDIT: If they are supposed to behave the same way, I don't understand the purpose of exposing the path.normalize(...) function when you can simply pass the path into path.resolve(...) Or, maybe, it's for documentation purposes. For example, they say in the documentation for path.resolve(...):
... The resulting path is normalized, and ...
Exposing the path.normalize(...) makes it easier to explain what "normalized" means? I don't know.
path.normalize gets rid of the extra ., .., etc. in the path. path.resolve resolves a path into an absolute path. Example (my current working directory was /Users/mtilley/src/testing):
> path.normalize('../../src/../src/node')
'../../src/node'
> path.resolve('../../src/../src/node')
'/Users/mtilley/src/node'
In other words, path.normalize is "What is the shortest path I can take that will take me to the same place as the input", while path.resolve is "What is my destination if I take this path."
Note however that path.normalize() is much more context-independent than path.resolve(). Had path.normalize() been context-dependent (i.e. if it had taken into consideration the current working directory), the result in the example above would've been ../node, because that's the shortest path one could take from /Users/mtilley/src/testing to /Users/mtilley/src/node.
Ironically, this means that path.resolve() produces a relative path in absolute terms (you could execute it anywhere, and it would produce the same result), whereas path.normalize() produces an absolute path in relative terms (you must execute it in the path relative to which you want to calculate the absolute result).
From the docs:
Another way to think of resolve is as a sequence of cd commands in a shell.
Links to path.resolve and path.normalize in the documentation. I mostly don't want to just provide links in an answer but the Node.js docs are very decent.

How can I copy picture and text from one file into another file dynamically using node.js

Suppose i have two files a_b_c_d.txt and e_f_g_h.png S,At runtime i.e., by using command prompt i have to create b folder inside that c folder inside that d folder inside that a.txt and same also for another file f->g->h->e.png and i have some text in a and image in epng . .So,how can I get values from those existing file into created files. .
You can find all the file system operations inside the fs module. http://nodejs.org/api/fs.html
But like tapan says if you need to do complex synchronous execution that manipulates the file system something like Bash will be a lot better suited for that.
So if I'm understanding you correctly you want to take a file named "a_b_c_d.txt" in some folder, and move that into a nested folder as:
./a_b_c_d.txt -> ./b/c/d/a.txt
The general solution would be:
Grab the file name using process.argv if it varies.
For example, if you supply the file as an argument to node, e.g.
node move.js "a_b_c_d.txt", the argument, "a_b_c_d.txt", will be in the argv array.
Process the file name using a combination of string and array methods.
Nodes current directory is stored in the __dirname global variable
if you need it.
You can split the extension from the rest of the path
using string's split(...) method.
For the above argument, split('.') will result in the array ['a_b_c_d', 'txt']
You can then split 'a_b_c_d' using '_',
and use various array operations to pull the file name 'a'
out of the array, so that you're left with the path ['b', 'c', 'd']
and the file name and extension sitting in their own variables somewhere.
Use fs.mkdirSync(...) on the path array to make each nested folder,
starting with b (e.g. using array's forEach(...) method).
You could also use the async fs.mkdir(...) and supply callbacks,
but the sync version is easier in this case.
Finally use fs.renameSync(...) to move ./a_b_c_d.txt to ./b/c/d/a.txt.
As you can see, python or bash (as tapan suggested) would probably be simpler for this use case, but if for some reason you have to use node, the above advice will hopefully be enough to get you started.

Resources