Compose path (with boost::filesystem) - path

I have a file that describes input data, which is split into several other files. In my descriptor file, I first give the path A that tells where all the other files are found.
The originator may set either a relative (to location of the descriptor file) or absolute path.
When my program is called, the user gives the name of the descriptor file. It may not be in the current working directory, so the filename B given may also contain directories.
For my program to always find the input files at the right places, I need to combine this information. If the path A given is absolute, I need to just that one. If it is relative, I need to concatenate it to the path B (i.e. directory portion of the filename).
I thought boost::filesystem::complete may do the job for me. Unfortunately, it seems it is not. I also did not understand how to test wether a path given is absolute or not.
Any ideas?

Actually I was quite misguided first but now found the solution myself. When "base" holds the path A, and filename holds B:
boost::filesystem::path basepath(base), filepath(filename);
if (!basepath.is_complete())
basepath = filepath.remove_leaf() /= basepath;
base = basepath.string();
It works with Linux at least (where it would be very easy to do without boost, but oh well..), still have to test with Windows.

Related

How to split Bazel file path into external dependency directory and relative path?

I'm working on a custom rule in skylark that is trying to use the proto compiler. Due to intricacies of how it works, I need to split a path into a directory for the external dependency and the path part that is relative to that.
Example1:
File:[/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19[source]]external/googleapis/google/devtools/build/v1/build_status.proto
I want the paths:
/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19/external/googleapis/
google/devtools/build/v1/build_status.proto
Example2:
File:[[/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19/execroot/bes_example]bazel-out/darwin_x86_64-fastbuild/genfiles]external/com_google_protobuf/google/protobuf/any.proto
I want the paths:
/private/var/tmp/_bazel_endobson/c56b77af296477cd0f319aa9d4ce1d19/execroot/bes_example/bazel-out/darwin_x86_64-fastbuild/genfiles/external/com_google_protobuf
google/protobuf/any.proto
The issue is that bazel allows accessing the root and root relative parts of the path, but doesn't give insight into if the path has the 'external/' part or not. The protocol buffer compiler needs this because it needs to know the directories that correspond to the root directories from the user's point of view so that it can use relative paths from the source.
Is there a principled way of detecting this other than hackily looking at the path to see if it has 'external' in it?
I'm afraid I cannot give you a really great answer here :( Eventually, we'd like to remove the "external" path segment, but it hasn't happened yet. The current rule is that you have it for source artifacts, but you don't have it for generated artifacts.
Thus, what I'd do is exactly what you suggest -- check if the first path segment is "external".

Metalsmith: How to use path()?

Metalsmith's documentation does not explain much about the path() function: #path(paths...): Resolve any amount of paths... relative to the working directory. This is useful for plugins who want to read extra assets from another directory, for example ./templates. That's it. That's the sum total of the documentation.
What arguments are expected and what do they do?
What I want to do is: Process different source directories according to different Metalsmith plugins. This seems to require me to create multiple templates/ directories under the separate source directories. If I want metalsmith-templates to look for templates under ../templates rather than ./templates, I would assume path() can do that... but in the absence of any meaningful documentation, I have no way to anticipate how to do it, or even whether it will work at all (short of reading the source code).
Answering my own questions:
path() is meant to be used in plug-in code, not the metalsmith project's index.js.
It takes a series of strings, which will be concatenated (with path separators) into a single path, which is then resolved relative to the metalsmith instance's given path.
E.g., from metalsmith-layouts:
var str = metalsmith.path(dir, data.layout || def);

what is url shorthand in a filesystem

This should be pretty simple I need know what dots mean in a url such as "../../../Program Files (x86)/Filed/examples/tmw_desert_spacing.png"
I'm assuming this is some kind of shorthand that means "the same as the current directory"/etc/folder/file.png a link to an article that explains this would be nice too, my google search turned up nothing since im not even sure this is called a url. thanks
more info: the program im writing won't except this as the file name, I need to konw what need to change to become acceptable.
According to RFC 3986:
The path segments "." and "..", also known as dot-segments, are
defined for relative reference within the path name hierarchy. They
are intended for use at the beginning of a relative-path reference
(Section 4.2) to indicate relative position within the hierarchical
tree of names.
The takeaway is that they have the same meaning as in paths on a linux or windows system - single dot means "the directory specified by the preceding part of the path", two dots mean "the parent directory of the directory specified by the preceding part of

Name of a path containing the complete file name?

For me, a path was always something that "walks the way to something", but without the "something".
Like a chicken following bread crumbs until it hits the target. But the target is not part of the path. That's what I believe.
So, example: C:/foo/bar = the path. C:/foo/bar/something.html = Path and the "Target".
Can someone tell me what are the correct terms here? How do I call such a path with file?
"Full path"?
"Full qualified path"?
"Path with File Name"? (not precise! "Path with File Name and Extension" ... way too long)
Sure there's a special name for this. Want to know! :)
Nice chicken example... I think you mean absolute path
but, It doesn't matter what the path points to, be it a directory, file, device or otherwise
Wikipedia says:
A path, the general form of a filename or of a directory name, specifies a unique location in a file system.
It doesn't even require an extension, as other mechanisms work out the filetype.
/foo/bar/file.txt = Absolute path
/foo/bar = An absolute path to a directory
../foo = A relative path to a directory, from current directory
./file.txt = A relative path to a file, from current directory (Unix)
file.txt = A relative path too
Also
Systems can use either absolute or relative paths. A full path or absolute path is a path that points to the same location on one file system regardless of the working directory or combined paths. It is usually written in reference to a root directory.
The distinction between files and directories isn't catered for with a path. A path is always a path to something, be it a file or a directory:
/a/b/c is the path to c regardless of what type (file, directory, device) the end point is.
Also checkout basenames
basename is a standard UNIX computer program, when basename is given a pathname, it will delete any prefix up to the last slash ('/') character and return the result. basename is described in the Single UNIX Specification and is primarily used in shell scripts.
From LINFO
A path is the address of an object
(i.e., file, directory or link) on a
filesystem.
So, unfortunately, you are looking for a specificity of terms that isn't part of the accepted usage. You'll have to define your own terms.
I beleive it is called "full name" regardless of the "target" type, just because everything in UNIX is a file, including a directory. So if a foo is the target (as you called it), then foo is the name, while C:\Direcotry\foo or /usr/bin/foo is the foo's full name.
i have been thinking about it too lately, because in Everything, the path do not include the "target" itself. but when i search in Wikipedia, it say that the target is included.
in your example, you have implicitly assume that there is "only one" target at the end of the bread crumbs. and someone tell the chicken to follow the bread crumbs and then it can get to the target.
what if there are 2 objects in the end? if someone did not tell which one is the target, e.g. include the target itself in the path, the chicken will never know its target.
you can also think like this: for a path which include the file, the target is not the file, but its content or some other imformation of the file.
back to the file system, assume there is several file in a folder. if file name is not included in its path, then they all have same path and you can not find a specific file through its path alone.

Deleting a temporary directory

I have this code,
showmessage('C:\TEMP\'+openfiles[openfilelist.ItemIndex].ID);
if removedir('C:\TEMP\'+openfiles[openfilelist.ItemIndex].ID) then
showmessage('Removed')
else
showmessage('Failed');
The message shows C:\TEMP\0 and this directory does exist as the program created it earlier and used files inside it and then later deletes them. I can see the files and directories so I know they're there. The program successfully deletes the files but does not remove the directory.
If I hardcode the directory it works - this means that it accepts the string
C:\TEMP\0 but does not accept C:\TEMP\'+openfiles[openfilelist.ItemIndex].ID both equate to C:\TEMP\0. I cannot hardcode these directories, so what can I do? How do I convert from a string + string to whatever removedir() is expecting. I looked this up at Delphi basics and it's expecting a string.
I'm confused, since string + string = string. What is going on?
Make sure that neither your program nor any other program have the directory as their current working directory. When you recompile the program this may no longer be the case, so it may be a red herring that the hardcoded value works for you.
In addition to the other good answers, you should not be storing your temp folder in C:\TEMP. Use the value returned from GetTempFilename, instead. Unlike C:\TEMP, this location (which varies by operating system) will work on all operating systems, and all levels of user access control. This also eliminates the risk that the location you have hardcoded might also be hardcoded into another system.
If I understood correctly, openfiles[openfilelist.ItemIndex].ID is a string that contains number?
If so, did you check that it does not contain blanks? Something like this:
filename := 'C:\TEMP\' + trim(openfiles[openfilelist.ItemIndex].ID);
showmessage(filename);
if removedir(filename) then
showmessage('Removed')
else
showmessage('Failed');
What type of objects are openfiles and openfilelist?
Do they open folders at all, if so they may still be open when your trying to delete the folder.

Resources