0

I'm working on a Mac desktop app and trying to run a shell script. I'm getting hung up on setting a launch path for the task. Here's the code:

    let path = fileURL.deletingLastPathComponent().relativePath

    //set new filename
    let strNewFileName = fileURL.deletingPathExtension().lastPathComponent.appending(".html")

    let newPath = path + "/" + strNewFileName

    //create script
    var strScript = "pandoc -s -o "
    strScript.append(newPath)
    strScript.append(" ")
    strScript.append(fileURL.absoluteString)

    //set storage path
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    var documentPath:URL = URL(string: documentsPath)!
    documentPath.appendPathComponent("pandoc.sh")

    var myURLComponents = URLComponents()
    myURLComponents.scheme = "file"
    myURLComponents.path = documentPath.absoluteString


    do {
        //write file
        try strScript.write(to: myURLComponents.url!, atomically: true, encoding: String.Encoding.utf8)

        //run script
        let myTask = Process()

        myTask.launchPath = "/usr/bin/env"
        myTask.arguments = [strScript]

        let myPipe = Pipe()
        myTask.standardOutput = myPipe

        myTask.launch()

        let data = myPipe.fileHandleForReading.readDataToEndOfFile()
        let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)

        print(output!)



    } catch {
        print(error.localizedDescription)
    }

This throws a no such file error:

env: pandoc -s -o /Users/stevensuranie/Desktop/MarkdownFiles/targeting-params-ios.html file:///Users/stevensuranie/Desktop/MarkdownFiles/targeting-params-ios.md: No such file or directory

Any help would be appreciated.

1 Answer 1

1

This line cannot work

var documentPath:URL = URL(string: documentsPath)!

URL(string is for URL strings including the scheme (file:// or https://), for file system paths you must use URL(fileURLWithPath.

However if you use the URL related API of FileManager you can avoid the init method at all.
A similar issue is absoluteString, never call it on a file system URL, use always path.

A second fatal issue is that each shell argument must be an item in the arguments array and the executable must be specified with the full path

//create script
let scriptArguments = ["/path/to/pandoc", "-s", "-o", newPath, fileURL.path]

//set storage path
let documentsURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let scriptURL = documentsURL.appendingPathComponent("pandoc.sh")

The following lines are redundant

var myURLComponents = URLComponents()
myURLComponents.scheme = "file"
myURLComponents.path = documentPath.absoluteString

The write the string to scriptURL

do {
    //write file
    try strScript.write(to: scriptURL, atomically: true, encoding: .utf8)
...

    myTask.arguments = scriptArguments

And finally don't use NS... classes in Swift

let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)

Use the native equivalent

let output = String(data: data, encoding: .utf8)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.