Comments (8)
Interesting question. And I think the answer is "it depends".
Without actually trying it, my thought would be to compare paths this way:
path($p1)->absolute eq path($p2)->absolute
(Assumes that CWD is useful for converting relative to absolute). Absolute will include a volume if one exists. (Though if a path is "/foo/bar", calling absolute on it will probably not add a volume to it, but 'realpath' would.)
To compare directories, use realpath
instead of absolute
:
path($p1)->realpath eq path($p2)->realpath
That latter is expensive but probably the most reliable because it actually checks the filesystem.
Though, actually, I haven't checked that realpath adds on a volume. I mostly trust Cwd for that. If you're on windows, see what happens and let me know.
from path-tiny.
The problem of using realpath
, is its easy for $p2
to not exist, ie: If the code I'm working with returns a list of paths, that may or may not exist, for comparison against a path that does exist, it gets a little messy.
Which means you have to do
my $test = path(...)->realpath;
grep { $_->exists and $_->realpath eq $test } map { path($_) } @user_paths
Though It might be simpler if it was implemented as a Path::Tiny
method
for my $user_path ( @user_paths ) {
if ( path($otherpath)->is($user_path) ) {
}
}
Though that would be preferable code imo vs this:
if( $somepath->stringifiy eq "/some/os/specific/string/" )
Surely,
if( $somepath->is( "/some/os/specific/string/" ) )
Will have less platform centric issues?
Not sure yet.
from path-tiny.
As I implied, but I guess need to be clearer about: the problem I have with an is
or matches
method is that "equality" is contextual. It could mean any of these:
- stringified paths are the same?
- stringified absolute paths are the same?
- paths resolve to the same physical directory?
And maybe other things I haven't thought about.
My suspicion is that stringified absolute paths are the thing that people most often would compare for equality, but that might not be true if ".." is involved. Consider this: foo
vs bar/../foo
. Are those equal or not? The relative forms aren't equal as strings. The absolute forms on Unix aren't equal (because absolute doesn't eliminate the ..
). The absolute forms on Windows are equal, because Windows collapses the bar\..
. The realpaths might be equal, but only if both paths actually exist and bar isn't a symlink.
I'm inclined to just add a documentation section (or a cookbook) with explaining this and with useful idioms and leave it at that.
For your case, how about this:
my $test = path(...)->realpath;
my @matches = grep { eval { $test eq path($_)->realpath } } @user_paths;
Path::Tiny overloads stringification, so a plain eq
should work. And the eval protects against the exception if the realpath doesn't exist. (For which I'm about to ship an improved exception message, too.)
from path-tiny.
For what I'm doing, adding exceptions to the flow seems like it would make things messier.
The path must exist anyway in order for the comparison to be valid, ie:
sub check_path_match {
my ( $self, $current, $other ) = @_;
# $current will always exist
# $other not existing is thus not a match
return unless path($other)->exists ;
return path($current)->realpath eq path($other)->realpath;
}
^ given this criteria, a testing to see if a path, which does exist matches some other path, if the other path does not exist, then it can't be a match.
So here, not wrapping in an eval
means any unexpected problems will still propagate
from path-tiny.
Depending on what path you're checking, realpath
can throw an exception. So you want to wrap it in an eval.
`path("/tmp/foo/bar/baz")->realpath`
If the final directory exists and the file doesn't, realpath is fine. But if you have intermediate directories that don't exist, then Cwd::realpath returns the empty string, which causes Path::TIny to throw an exception.
But if "not existing" is another form of "not matching" to you, then your approach seems fine.
from path-tiny.
Specifically, my list of paths come from tools like File::HomeDir
, and Config.pm
, and I'm always checking to see if a given path which does exist, if that given path is found amongst one of the tool provided path lists.
If the path lists returned by the tools contain paths that don't exist, then my logic is that the given path which does exist cannot be amongst those paths that were returned that did not exist.
For instance, if I'm inspecting the path /home/kent/foo
and trying to see if that path is one of the File::HomeDir
paths, I can quickly determine if ->my_desktop
returns /home/kent/Desktop
and /home/kent/Desktop
does not exist, then /home/kent/foo
cannot be the same path has /home/kent/Desktop
Only once /home/kent/Desktop
exists am I even interested in whether or not it is the same realpath as /home/kent/foo
Though I think I have enough to go on now, and my approach doesn't have any obvious flaws to me ( Well, other than being obviously inefficient )
The only room I think for things to be unexpected is if a path ->exists
but for some reason cannot be ->realpath
'd, and I'm now basically asking if there's any scenarios where ->exists
might return true, and ->realpath
may still fail.
from path-tiny.
On Mon, Oct 14, 2013 at 10:10 AM, Kent Fredric [email protected]:
The only room I think for things to be unexpected is if a path ->existsbut for some reason cannot be
->realpath'd, and I'm now basically asking if there's any scenarios where
->exists might return true, and ->realpath may still fail.I don't think so. The opposite can be true -- you can have a valid
realpath for a non-existent file/directory in an existing directory. But
if the file or directory exists, then realpath should be able to resolve it.
The exception would be if you're somehow in a deep directory and don't have
permissions to traverse into parent directories, but that's a pretty
unusual case.
David
David Golden [email protected]
Take back your inbox! → http://www.bunchmail.com/
Twitter/IRC: @xdg
from path-tiny.
The exception would be if you're somehow in a deep directory and don't have permissions to traverse into parent directories, but that's a pretty unusual case.
Given I don't even know exactly what my code should do in such a scenario yet, it seems acceptable that my code will just die horribly instead of just silently plodding ahead and accidentally potentially causing more damage
( ie: If somebody was using this mechanism with some recursive tree removal , I'd rather fail early and go "not sure whats going on here" than to silently go "Uhh .... sure, these are the droids you are looking for, continue" )
Thanks for the good feedback, I think this issue can be closed now.
from path-tiny.
Related Issues (20)
- RFC: `with( $callback )` method HOT 1
- Tests fail on Windows 11: Failed test 'lstat' ... Error resolving realpath HOT 2
- mkdir fails if the directory exists HOT 1
- Broken tilde expansion for home directories of accounts with special characters HOT 1
- Windows 11: Failed test 'lstat' at t\filesystem.t line 420 (lstat->size returns zero) HOT 1
- Windows 11: Failed test 'relative symlinks with updir' at t/symlinks.t line 31. HOT 1
- Windows 11: Failed test 'Follow symlinks' at t/recurse.t line 139 HOT 1
- t/basic.t fails with ~root = / HOT 9
- Windows 11: Failed test "relative on absolute paths with symlinks" in t/rel-abs.t
- Feature request: $path->children('*.txt') or $path->glob('*.txt')
- A File::Temp object is created as an opened file, but the cached_temp is not open HOT 1
- Feature request: slurp_* support for chomp argument
- RFE: copy() & move() on existing Path::Tiny file object: return existing object
- Windows 11 fails test t/basic.t
- Feature Request: limit path->lines result to those matching pattern HOT 2
- Feature Request: integrate functionality of File::pushd
- Add is_temp, is_tempfile and is_tempdir predicates
- Support size option for digest to limit to first n bytes HOT 1
- Misleading error message for spew in non-existent dir HOT 10
- Adding 'dot' child
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from path-tiny.