In PyQt4 on Apple Mac OS X, we get a file reference URL to a drag-and-dropped file in the following format:
file:///.file/id=123456.78901
This, interestingly, is not a valid file URL, or at least it doesn't transparently resolve in most applications — there is no /.file/id=... file in the filesystem.
Using just shell, how do I dereference this NSURL or file reference or alias (or whatever it's called) into a valid path to file on the filesystem?
In Swift you can use URL.standardized to get the valid path from a reference URL. So in Swift 4 - to get the file name from a drag-and-dropped file you'd do something like...
let fileType = NSPasteboard.PasteboardType (kUTTypeFileURL as String)
extension NSPasteboardItem {
func fileURL ()->URL? {
if let refURL = self.string(forType: fileType) {
return URL (fileURLWithPath: refURL).standardized
}
return nil
}
}
One can use osascript, an AppleScript interpreter available on default OS X installs, run with the following script:
osascript -e 'get posix path of posix file "file:///.file/id=123.456" -- kthxbai'
Prints /Users/josh/Downloads/paste-10837081.py.
That is a NSURL object, to get a path from it:
NSString *filePath = [fileURL path];
This can also be accomplished in Python using the PyObjC bridge.
from Foundation import NSURL # depends on PyObjC
# convert a URL file reference to a POSIX path
NSURL.URLWithString_('file:///.file/id=6571367.8602676692').path()
# convert a path file reference to a POSIX path
NSURL.fileURLWithPath_('/.file/id=6571367.8602676692').path()
Be sure you to select the appropriate NSURL method for your data type or else you'll get the wrong value back.
Resources
NSURL API doc
API discussion of file reference URLs
PyObjC
Related
I want to move a file from a folder to another folder
I used
[[NSFileManager defaultManager]moveItemAtPath:#"Folder/Filename.fileExtension" toPath:#"FolderToMoveTheFile" error:nil];
Is there something else to type in error: ?
Why it isn't move my file?
You would get the error by doing this:
NSError* error;
if (![[NSFileManager defaultManager]moveItemAtPath:#"Folder/Filename.fileExtension" toPath:#"FolderToMoveTheFile" error:&error])
{
// handle error, typically using the NSError object pointed to by the error variable
// In an app, you might want to pass it to a -presentError:... method of a convenient responder
// This is good enough for debugging:
NSLog(#"failed to move file: %#", error);
}
The second path that goes after toPath: must be the path including the file name at the destination. It is not correct to just specify the path to the directory into which you want to move the file.
Also, you should typically use absolute paths, not relative paths. You can use relative paths but that then depends on the current working directory for the process. That's arbitrary for apps launched from the Finder or Dock. It's really only meaningful for command-line tools launched from a shell (e.g. a Terminal window) where the user might be expected to cd to a directory and then provide relative paths as command-line arguments.
I am trying to write a Mac app that converts files. I am stuck at the beginning because my app cannot open local files, at least while running in the debugger. I use the NSOpenPanel to create a valid file NSURL:
“file:///Volumes/Seagate_1tib/projects/dataskunk/wasteproduct.xml”
But somewhere in xcode, or the debugger or whatever, this gets mangled into
"/Users/charlweed/Library/Developer/Xcode/DerivedData/dataskunk-ghkiumvdkopxarhavynetidlqxio/Build/Products/Debug/file:/Volumes/bigdrive/dataskunk/wasteproduct.xml"
Reading the file then fails with a "No such file or directory error".
How do I prevent this mangling during development?
For example, this gives the error, no matter what file is chosen:
let fileResult = openFileDialog("Choose File", message:"Message")
let xmlInFileURLOpt: NSURL? = NSURL.fileURLWithPath(fileResult)
if let xmlInFileURL = xmlInFileURLOpt
{
var xmlFileError: NSError?
if !xmlInFileURL.checkPromisedItemIsReachableAndReturnError(&xmlFileError){
println("\(xmlFileError)")
return
}
}
The answer is that NSURL.fileURLWithPath() does not take a URL-path as an argument, only a filesystem-path. So "file:///Volumes/disk/file.xml" is wrong, "/Volumes/disk/file.xml" is correct.
The mangling is NSURL prefixing the current directory onto what it thinks is a relative filesystem-path String.
env: OSX 10.10 / iPhoto 9.6 / Ruby 2.2
in a ruby script, I am trying to open an xml file from the 'iPhoto Library' to get the album list.. but I got an error :
f = File.open(#xmlpath)
Errno::ENOENT: No such file or directory # rb_sysopen - /Users/myself/Pictures/iPhoto%20Library/AlbumData.xml
first, I defined the 'iPhoto Library' path in my user path :
PhotoLib = File.expand_path(File.join("~","Pictures","iPhoto Library")
then I defined the #xml file path ( escaping the embedded spaces )
#xmlpath = URI.escape(File.join iPhotoLib, "AlbumData.xml")
finally I try to open the xml file
f = File.open(#xmlpath)
but it raises the 'No such file or directory' error... where am I wrong ?
the file exists in the "iPhoto Library" content ...
You shouldn't be using URI.escape - that is for urls but what you pass to File.open is a path on your local filesystem, not a url. In particular percentage escapes ("%20") don't make sense to your filesystem
I should use
library_path = Pathname.new(ENV["HOME"]) + "Pictures" + "iPhoto Library.photolibrary"
xml_path = library_path + "AlbumData.xml"
f = File.open(xml_path)
Pathname handle correctly it ....
I have copied files like this from an application before and have copied the code exactly as it appears in another app but for what ever reason when it try to run this particular code it will only create the new directory.
It will not however save the binary file I have saved in supporting files in the main bundle to the new directory. I have done a fair amount of googling and searching stack overflow and have decided I might have to post something here.
let path = NSBundle.mainBundle().resourcePath?.stringByAppendingPathComponent("youtube-dl")
let destination = "~/Library/Application Support/Youtube DLX/"
let destinationPath = destination.stringByStandardizingPath
NSFileManager.defaultManager().createDirectoryAtPath(destinationPath, withIntermediateDirectories: true, attributes: nil, error: nil)
NSFileManager.defaultManager().copyItemAtPath(path!, toPath: destinationPath + "youtube-dl", error: nil)
note that the file that I am trying to copy has no extension so the full name is just "youtube-dl"
The result of
let destinationPath = destination.stringByStandardizingPath
has no trailing slash, so you are trying to copy the file to
"~/Library/Application Support/Youtube DLXyoutube-dl"
You should use
destinationPath.stringByAppendingPathComponent("youtube-dl")
to generate the target path as you already did for the source path.
Generally (as just mentioned in a comment), you should use the error parameter and
check the return value for success, for example
var error : NSError?
if !NSFileManager.defaultManager().copyItemAtPath(..., error: &error) {
println("copy failed: \(error)")
}
I have to run a script from Objective C code. my script server.js is located at the path
/Users/SS/Desktop/iPhone App/Appium.app/Contents/Resources/node_modules/appium/server.js
In objective c code, I set the path as
[self.serverTask setCurrentDirectoryPath:[NSString stringWithFormat:#"%#/%#", #"/Users/SS/Desktop/iPhone App/Appium.app/Contents/Resources", #"node_modules/appium"]];
launch path with argument
[self.serverTask setLaunchPath:#"/bin/bash"];
[self.serverTask setArguments: [NSArray arrayWithObjects: #"-l", #"-c", nodeCommandString, nil]];
The problem I am facing is that when I am running XCode application, it is receiving only the path before the space (i.e. /Users/SS/Desktop/iPhone) and through an error
/bin/bash: /Users/SS/Desktop/ab: No such file or directory
Is there is an idea by which I can access path after the spaces.
send the path of your appium inside double quotes.
Change your path like this./
[self.serverTask setCurrentDirectoryPath:[NSString stringWithFormat:#"%#/%#", #"/Users/SS/Desktop/iPhone\ App/Appium.app/Contents/Resources", #"node_modules/appium"]];
Add \ before the space.
Send the path of your appium inside double quotes like following.
[self.serverTask setCurrentDirectoryPath:[NSString stringWithFormat:#"%#/%#", #"/Users/SS/Desktop/iPhone\ App/Appium.app/Contents/Resources", #"node_modules/appium"]];