Where do files go when you delete them programatically with swift? - swift

Where do files go when you delete them programatically? I deleted them with this code, but the Trash for today is empty. Is it possible to retrieve them?
let filemgr = NSFileManager.defaultManager()
do{
let filelist = try filemgr.contentsOfDirectoryAtPath(fontFolderPath)
for filename in filelist {
do{ try filemgr.removeItemAtPath(fontFolderPath+filename)} catch{}
}
}catch{}

Using the URL related API of NSFileManager you have two options:
func removeItemAtURL(_ URL: NSURL) throws
deletes the item immediately like /bin/rm in Terminal.app and has the same functionality as removeItemAtPath.
func trashItemAtURL(_ url: NSURL,
resultingItemURL outResultingURL: AutoreleasingUnsafeMutablePointer<NSURL?>) throws
moves the item to the trash folder returning the item’s location in the trash via the inout pointer.

The removeItemAtPath method deletes them. They're gone. If you want to move something to the trash, you need to use NSWorkSpace. You can see an example of moving an entire directory to the trash here: Move directory to trash

basically unixy systems manage files the same way, there is a ref count, that is the number of hard links + times the file is open... So you can rm an open file, and the file will still exist, you can write to it, and read from it, with a valid file descriptor or FILE * stream object, then when it is closed the file will actually be removed from the disk...
int fd = open("somefile", O_RDWR);
unlink("somefile"); // removes somefile from the directory listing, but not disk
write(fd, "hello", 5);
lseek(fd,0,SEEK_SET); // seek to start of file
char buffer[6] = {0};
read(fd,buffer,5); // reads in "hello"
close(fd); // last reference removed, file is removed.
if you want to move a file to the Trash, that is a different operation and specific to OS X and iOS

Related

How do you zip a directory in Swift without compressing one of the files it contains to make an ePub file?

I am trying to programmatically create an ePub file. I am following this tutorial. The tutorial says to "make the .epub container that all these files go in" by:
Create an empty .zip file with whatever name you like (See notes below for detailed instructions on how to do this.)
Copy the mimetype file into the zip file (don't use compression on this file)
Copy the rest of the files and folders mentioned above into the zip file *
Re-name the .zip extension to .epub
These are the last few steps of the process. I have all the files that need to go into the zip ready. I know the files work because I used a third party program (eCanCrusherMac.1.2.1) to do these finals steps and the product it creates is an ePub file that loads in the Books eReader (made by Apple).
I used the below code to zip the desired directory. I found this code on here Stack Overflow
func zip(itemAtURL itemURL: URL, in destinationFolderURL: URL, zipName: String) throws {
var error: NSError?
var internalError: NSError?
NSFileCoordinator().coordinate(readingItemAt: itemURL, options: [.forUploading], error: &error) { (zipUrl) in
// zipUrl points to the zip file created by the coordinator
// zipUrl is valid only until the end of this block, so we move the file to a temporary folder
let finalUrl = destinationFolderURL.appendingPathComponent(zipName)
do {
try FileManager.default.moveItem(at: zipUrl, to: finalUrl)
} catch let localError {
internalError = localError as NSError
}
}
if let error = error {
throw error
}
if let internalError = internalError {
throw internalError
}
}
I took the file this function gives me, made sure it had the epub extension and tried to open it using the Books app but it fails to load. The code produces a zip file that I can interact with normally in Finder so I know the function works.
I believe the issue is with the "mimetype" file getting compressed. I have taken a valid ePub, changed the file's extension to zip, unzipped it and then rezipped it using Finder and tried to open it again with no other changes and it doesn't work. As you can see in the instructions from the tutorial at the top of this post the "mimetype" file can't be compressed.
This is a Swift app on Mac.
I looked into the different NSFileCoordinator.ReadingOptions and NSFileCoordinator.WritingOptions and searched on Stack Overflow and elsewhere online but I can't find anything on how to create a zip file in Swift without compressing a file contained in the zip file.
I was able to get the ePub to open using ZIPFoundation:
try FileManager.default.zipItem(
at: bookURL,
to: ePubURL,
shouldKeepParent: false,
compressionMethod: .none,
progress: nil
)

Swift delete file (Move to Bin) with (Put Back) functionality using FileManager.default.trashItem

Using the following code I am able to delete a file which is moved to trash, but there is no "Put Back" functionality. When I right click the file in trash only delete immediately option is available.
let srcURL = URL(fileURLWithPath:filename!)
var trashedPath: NSURL!
try! FileManager.default.trashItem(at: srcURL, resultingItemURL: &trashedPath)
My program is a Finder Quick Action Service written in Swift 5.4, where I am passing one or more filenames with path of image files like .heic, .png, .tiff, and converting it to jpg. I then want to delete the source file and move them to trash. As the files can be from different directories I want to provide the facility where the user can restore the deleted source file to its proper place.
What should be done to get "Put Back" option?
As far as my research suggest that the "Put Back" functionality is only available thru Finder. I came across Trash - Trash by ali-rantakari on github
Now I have to implement a way to run this command in swift, which is as follows.
#discardableResult
func shell(_ args: String...) -> Int32 {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
shell("trash","-F", "\(filename!)")

Is there a way to work with FileManager and NSBundle to get all the applications that support a given type of file in the /Applications directory?

I'm creating a Commandline tool that will get an input from a user to search for a specific application that supports a certain file extension. For example, if I enter mp4, it will probably show me QuickTime. I'm looking for the specific FileManager manipulation to achieve this in Swift.
I think you are looking for NSWorkspace.urlForApplication(toOpen:). It finds the application that would be opened if you had double clicked on a file, and returns its URL. Since it requires a file to work, you need to first create a temporary empty file somewhere, with the desired extension, then call this method.
let tempFileURL = FileManager.default.temporaryDirectory.appendingPathComponent("foo.mp4")
FileManager.default.createFile(atPath: tempFileURL.path, contents: nil, attributes: nil)
// this gives me the URL for QuickTime Player:
// file:///System/Applications/QuickTime%20Player.app/
let url = NSWorkspace.shared.urlForApplication(toOpen: tempFileURL)

Xcode Project Folder Structure

I am using the latest XCode / Swift 3.0 and facing some problems:
I created a folder in /MyProject/MyProject/Assets/Subfolder1 and stored a few hundred .txt files in it to iterate over the files inside the Subfolder1 with the following code:
let fm = FileManager.default
fm.enumerator(atPath: "/MyProject/Assets/Subfolder1")?.forEach({ (e) in
if let e = e as? String, let url = URL(string: e) {
doSomethingWith(url.pathExtension)
}
})
But I cannot find any files. I tried some variations ("/Assets/Subfolder1/" and "/MyProject/MyProject/Assets/Subfolder1"), all are not working.
What is the correct path that I have to specify?
Best
Chris
First off, make sure you have added the actual folder to the Xcode project. You can do this simply by dragging and dropping the folder into your project. After you drag and drop, this window should appear
Make sure you select Create folder references and Copy items if needed. This will make sure that the entire folder is constantly synced inside your Xcode project. Then to verify that the assets will be transferred to your device when building the project, go into Build Phases and then to Copy Bundle Resources and you should see the name of the folder, in my case, I have named it TextFiles.
Now because you have added your folder into the application's Main Bundle, you can access it by doing this:
let fm = FileManager.default
let path = Bundle.main.resourcePath?.appending("/TextFiles")
fm.enumerator(atPath: path!)?.forEach({ (e) in
if let e = e as? String, let url = URL(string: e) {
doSomethingWith(url.pathExtension)
}
})
The reason we need to do the Bundle.main.resourcePath before it and can't simply say /TextFiles is because if we say /TextFiles it looks for that folder starting from the system root, which is why it wasn't working before. It would be like having a folder in C:/Users/Abc123/Documents/TextFiles but the system is looking for it in C:/TextFiles.

Swift 2.0 - Unable to Write to Text File (OS X)

I have a text file that I will be reading and writing to. I have gotten the code to read successfully, but am unable to write to the text file again. I want to overwrite everything (not amend).
if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
let path = dir.stringByAppendingPathComponent("airports.txt")
var strTextToWrite:String = String()
strTextToWrite = "Test"
do {
try strTextToWrite.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding)
}
catch { print("Error") }
}
The above code doesn't throw an error (i.e. the word 'Error' isn't printed as per my catch code), but the text file remains unedited, retaining the value it had before the code was run.
The text file is contained inside the X-Code project as shown below:
I'm at a real loss here, I don't understand why the code isn't working. I have confirmed that it is being run (by printing the value of strTextToWrite before and after the do statement, and it is definitely running through the do block of code because it isn't being caught by the catch block. The only thing I can think of is that the code is pointing at the wrong file (but the file name is correct, as you can verify with the screenshot above).
What am I doing wrong? Thanks in advance.
You are looking at 2 different files: the one you write to is ~/Documents/airport.txt while the one you see (and check) in Xcode is located in your project folder. To see the update, you need to reference the file in Xcode, not make a copy of it.
Right click airport.txt in your Project Navigator and click Delete > Move to Trash
Go to ~/Documents/airport.csv and drag it into your Xcode project. Do not add it to any target and unselect "Copy Items if Necessary"
You now have created a link to the file.
Modifying files in your bundle is generally a bad idea. If you need a place to output a temporary file, use the app's subfolder under ~/Application Support or the system's temp folder.