代码之家  ›  专栏  ›  技术社区  ›  pkamb santoshIOS

如何通过NSUserUnixTask传递参数,然后通过脚本访问?

  •  5
  • pkamb santoshIOS  · 技术社区  · 6 年前

    NSUserScriptTask NSUserAppleScriptTask NSUserAutomatorTask

    Passing variables to an AppleScript

    Setting NSUserAutomatorTask variables without requiring Automator Workflows to declare that variable

    就这样离开了 NSUserUnixTask ,不支持设置变量。相反,它支持 [String] arguments .

    let folderURL: String? = "/files/"
    let fileURLs: [String] = ["/files/file1", "/files/file2"]
    let selectionType: Int? = 1
    
    let arguments: [String] = ["how", "should", "arguments", "be", "formatted", "?"]
    
    let unixScript = try! NSUserUnixTask(url: url)
    unixScript.execute(withArguments: arguments) { (error) in
        if let error = error {
            print(error)
        }
    }
    

    3个swift变量必须压缩成一个 [字符串] NSUserUnixTask任务 用作 参数。

    #! /bin/bash 
    say "How should the script then access/parse the arguments?"
    say $@ #says the arguments
    

    基于脚本作者的易用性,Swift代码应该如何将其信息格式化为参数 [字符串] ?

    可以提供什么样的样板代码来允许从脚本轻松而实用地访问参数?

    1 回复  |  直到 6 年前
        1
  •  3
  •   djromero    6 年前

    有很多方法可以做到这一点,这取决于shell脚本程序员的期望。如果我是他们中的一员,我会要求你保持简单:

    • 位置参数(开始时强制参数的固定数量)
    • 可选的命名参数(样式的任何参数 -flag value
    • 更多参数(数量可变的附加参数)

    按照您的示例,稍加修改:

    import Foundation
    
    let shellScript = CommandLine.arguments[1]
    
    let folderURL: String = "/files/"
    let fileURLs: [String] = ["/files/file1", "/files/file2"]
    let selectionType: Int? = 1
    
    var arguments = [String]()
    
    // script.sh <folder> [-type <type>] file1, file2, ...
    
    arguments.append(folderURL)  // <folder> is mandatory
    
    if let type = selectionType {    // -type <type> is optional
        arguments.append("-type")   
        arguments.append("\(type)")
    }
    
    arguments += fileURLs  // file1, ... (if it can't be empty check it here)
    
    assert(FileManager.default.fileExists(atPath: shellScript))
    let unixScript = try! NSUserUnixTask(url: URL(fileURLWithPath: shellScript))
    let stdout = FileHandle.standardOutput
    unixScript.standardOutput = stdout
    
    unixScript.execute(withArguments: arguments) { error in
        if let error = error {
            print("Failed: ", error)
        }
        exit(0)
    }
    
    dispatchMain()  // I'm not swift script expert, there may be a better way
    

    以及相应的shell脚本:

    #!/bin/bash
    
    # mandatory positional arguments
    
    FOLDER=$1 && shift
    # other mandatory arguments goes here
    
    TYPE=7  # default type
    FILES=()
    
    while [[ $# -gt 0 ]]; do
        arg=$1
        case $arg in
            -type) 
                TYPE=$2 && shift && shift
                ;;
            # other named parameters here
            *)
                FILES+=($1) && shift
                ;;
        esac
    done
    
    echo FOLDER: '<'${FOLDER}'>'
    echo TYPE: '<'${TYPE}'>'
    echo FILES: '<'${FILES[@]}'>'
    
    exit 0
    

    例子:

    ScriptRunner /path/to/script.sh
    

    FOLDER: </files/>
    TYPE: <1>
    FILES: </files/file1 /files/file2>
    

    我使用swift包管理器构建:

    // swift-tools-version:4.2
    
    import PackageDescription
    
    let package = Package(
        name: "ScriptRunner",
        dependencies: [],
        targets: [
            .target(name: "ScriptRunner", dependencies: [])
        ]
    )