C++ - get file path on Mac OSX - c++

How would I get the full path to a specific file (on a system running OSX) once the file name is given by the user on a console application?
Any links or help would be great thanks.

You need to write a filesystem walker. C++ filesystem library will be of use. Start from your initial directory and start iterating. You can use DFS/BFS or your own custom algorithm
Another choice would be to simply see find commands source on Linux/Mac.
Edit 1: If you do not want to write a program then use terminal and fire following:
find / -name <whatever your filename is>

Related

How to get file path when opening a file from Finder

I have built a C++ cross-platform application and am struggling with how to get it to work correctly on macOS.
So far, I'm able to run the application manually with the command open /Applications/myApp.app --args /path/to/myFile.ply.
I have associated all ply files with my application but when I double click on it in the finder, the file path is not in argv argument list.
How can I get the double-clicked file path in my application?
You'll need an event loop, normally done using the NSApplicationMain function. Then you need to receive an Apple Event telling what file(s) to open. It will be much easier if you are willing to use some Objective-C or Swift, rather than pure C++. In Objective-C, you'd make an object that conforms to the NSApplicationDelegate protocol and that implements a method application:openURLs: or application:openFile:.
#JWWalker has explained how to solve your problem by altering your code to cope with the macOS GUI environment. Here is a different approach which avoids messing with your C++. Pick the one that suits you needs best.
If your cross-platform application is designed to run from the shell prompt you might want to run it within the macOS Terminal app. You can do this using a small AppleScript application which accepts the file paths passed by the Finder and invokes the Terminal app to run your C++ code.
To do this open Script Editor, you will find it inside Utilities in Applications. Enter the following:
on open passedItems
set convertedPaths to ""
# convert passed macOS paths to posix paths
repeat with nextItem in passedItems
set posixPath to the POSIX path of nextItem # convert macOS alias to posix path
set convertedPaths to convertedPaths & " '" & posixPath & "'" # place in quotes to protect any spaces
end repeat
tell application "Terminal" # open (if required) and activate Terminal
activate
do script "echo " & convertedPaths # just run echo - use the path to your C++ binary instead
end tell
end open
If you can program in C++ you can probably figure that out, if not search for AppleScript and all will become clear.
Now save this as an application, for this demo it was saved in /tmp/bridge (aka /private/tmp/bridge on macOS) as "Bridge.app".
Now create some test files with a suitable extension, e..g something like:
$ cd /tmp/bridge
$ touch a.bridgeDemo 'b c.bridgeDemo'
From Terminal you can open /tmp/bridge in a Finder window using:
$ open /tmp/bridge
In the Finder select any of your test files, do a Get Info and set the file to open with Bridge and then hit Change All...
Now try it: select the test files in the Finder and open them. You should see Terminal open/activate and show you something like:
$ echo '/private/tmp/bridge/a.bridgeDemo' '/private/tmp/bridge/b c.bridgeDemo'
/private/tmp/bridge/a.bridgeDemo /private/tmp/bridge/b c.bridgeDemo
$
Now edit the AppleScript to run your compiled C++ instead of echo and save it in a suitable location. HTH

"Embedding" a folder into a C/C++ program

I have a script library stored in .../lib/ that I want to embed into my program. So far, that sounds simple: On Windows, I'd use Windows Resource Files - on MacOS, I'd put them into a Resource folder and use the proper API to access the current bundle and it's resources. On plain Linux, I am not too sure how to do it... But, I want to be cross-platform anyway.
Now, I know that there are tools like IncBin (https://github.com/graphitemaster/incbin) and alike, but they are best used for single files. What I have, however, might even require some kind of file system abstraction.
So here is the few guesses and estimates I did. I'd like to know if there is possibly a better solution - or others, in general.
Create a Zip file and use MiniZ in order to read it's contents off a char array. Basically, running the zip file through IncBin and passing it as a buffer to MiniZ to let me work on that.
Use an abstracted FS layer like PhysicsFS or TTVFS and add the possibility to work off a Zip file or any other kind of archive.
Are there other solutions? Thanks!
I had this same issue, and I solved it by locating the library relative to argv[0]. But that only works if you invoke the program by its absolute path -- i.e., not via $PATH in the shell. So I invoke my program by a one-line script in ~/bin, or any other directory that's in your search path:
exec /wherever/bin/program "$#"
When the program is run, argv[0] is set to "/wherever/bin/program", and it knows to look in "/wherever/lib" for the related scripts.
Of course if you're installing directly into standard locations, you can rely on the standard directory structure, such as /usr/local/bin/program for the executable and /etc/program for related scripts & config files. The technique above is just when you want to be able to install a whole bundle in an arbitrary place.
EDIT: If you don't want the one-line shell script, you can also say:
alias program=/wherever/bin/program

Terminal Command Output to array in CPP

I have a folder and subfolder which contain many HTML files. I want to store all the html file paths to an array. I am using C++ and ubuntu.
I know a terminal command - find . -name *.html which gives me all the html file paths.
I want to use these paths to create PDF of these HTML files using WKHTMLTOPDF and threading. How to store these paths and use it?
You could brute-force it by using std::system
http://en.cppreference.com/w/cpp/utility/program/system
to execute your find command and use the output in a C++ program. Or read up on file system traversal in Steven's APUE ('Advanced Programming in the Unix Environment) and do it yourself. Begin with man 3 stat.

How to find all the hard and symbolic links to a file/folder (Windows and UNIX)?

How to find all the hard and symbolic links to a file/folder in Windows (using standard OS functions)?
What is opposed to UNIX?
From this nice tutorial for linux:
https://jackal.livejournal.com/2164247.html
Get the inode number:
ls -i FILENAME
Find file by inode number:
find / -inum INODE-NUM-FROM-ABOVE
Optionally restrict find to speed up the search.
Example:
> ls -i myfile.csv
74714625 myfile.csv
> find ~/myfolder/ -inum 74714625
/home/me/myfolder/myfile.csv
/home/me/myfolder/another/path/another_filename_with_same_inode.csv
Symlinks:
You´ll have to search all files on all hard disks etc.etc. and check each of them individually. Otherwise it´s not possible to get a list of symlinks for a specific file.
For Linux, How do you determine using stat() whether a file is a symbolic link? may help.
For Windows ... well, Reparse points are not explainable in one line.
It´s not trivial to check if a file is a symlink from C++.
Hard links:
Linux: Again (usually) not possible without searching all files and checking the inode number.
Windows: Depending on the used file system, FindFirstFileName and FindNextFileName
could be useful, but as said, they won´t always work (ReFS...)

How to use Instruments Time Profiler with Executable

I'm trying to use Mac Instruments Time Profiler to optimize my code for building a MandelBox. I found how to make my executable my target process, but when the program runs, it gives me an error in the Console window saying it cannot find the .txt file associated with the program.
Do I need to tell the profiler where to look to find the file? The text file is already in the same directory as the executable. Any thoughts? Thanks.
This problem is not unique to Instruments. The same thing would presumably happen if your current working directory was something other than the location of your program. For example, if you were to do cd / ; /path/to/yourprogram.
You either need to make your program find its own location and then find its text file as a sibling in the containing directory or take the path of the text file as an argument. Or, you will always have to set the working directory to your program's location before invoking it.
That last approach is an immediate workaround for the problem with Instruments. On the panel where you choose the target executable, you can also configure various parameters, such as arguments, environment variables, and the working directory. Set the working directory to the directory that contains the text file and it should work.