আমি কীভাবে একটি সুইফ্ট স্ক্রিপ্টে টার্মিনাল কমান্ড চালাব? (যেমন এক্সকোডবিল্ড)


91

আমি আমার সিআই ব্যাশ স্ক্রিপ্টগুলি সুইফ্টের সাথে প্রতিস্থাপন করতে চাই। আমি কীভাবে সাধারণ টার্মিনাল কমান্ডের অনুরোধ জানাতে পারি না lsorxcodebuild

#!/usr/bin/env xcrun swift

import Foundation // Works
println("Test") // Works
ls // Fails
xcodebuild -workspace myApp.xcworkspace // Fails

$ ./script.swift
./script.swift:5:1: error: use of unresolved identifier 'ls'
ls // Fails
^
... etc ....

উত্তর:


138

আপনি যদি সুইফট কোডে কমান্ড আউটপুট ব্যবহার না করেন তবে নিম্নলিখিতগুলি যথেষ্ট হবে:

#!/usr/bin/env swift

import Foundation

@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("ls")
shell("xcodebuild", "-workspace", "myApp.xcworkspace")

আপডেট হয়েছে: সুইফট 3 / এক্সকোড 8 এর জন্য


4
'এনএসটিস্ক'-এর নাম পরিবর্তন করে' প্রক্রিয়া 'করা হয়েছে
ম্যাটিউজ

4
প্রক্রিয়া () এখনও সুইফট 4 এ রয়েছে? আমি একটি অপরিবর্তিত প্রতীক পাচ্ছি। : /
আর্নাল্ডো ক্যাপো

4
@ আর্নাল্ডো ক্যাপো এটি এখনও আমার পক্ষে ভাল কাজ করে! এখানে একটি উদাহরণ রয়েছে:#!/usr/bin/env swift import Foundation @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("ls")
করপ্রেজগুলি

4
আমি চেষ্টা করেছি যে আমি পেয়েছি: আমি চেষ্টা করেছি যে আমি পেয়েছি: i.imgur.com/Ge1OOCG.png
cyber8200

4
প্রক্রিয়াটি কেবল ম্যাকোএসে উপলব্ধ
অগভীর কথা

93

আপনি যদি কমান্ড লাইনে (ঠিক সমস্ত আর্গুমেন্ট পৃথকীকরণ না করে) কমান্ড লাইনের আর্গুমেন্টগুলি "হুবহু" ব্যবহার করতে চান তবে নীচের চেষ্টা করুন।

(এই উত্তরটি লেগোএলসের উত্তরের উন্নতি করে এবং সুইফট 5 এ ব্যবহার করা যেতে পারে)

import Foundation

func shell(_ command: String) -> String {
    let task = Process()
    let pipe = Pipe()
    
    task.standardOutput = pipe
    task.arguments = ["-c", command]
    task.launchPath = "/bin/zsh"
    task.launch()
    
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8)!
    
    return output
}

// Example usage:
shell("ls -la")

7
এই উত্তরটি সত্যই অনেক বেশি হওয়া উচিত কারণ এটি পূর্ববর্তীগুলির অনেকগুলি সমস্যার সমাধান করে।
স্টিভেন হেপটিং 21

4
+1 এটা তোলে OSX ব্যবহারকারীদের জন্য উল্লেখ করা উচিত /bin/bashবোঝায় bash-3.2। আপনি যদি /usr/bin/env bash
বাশের

কেউ এই সাহায্য করতে পারেন? যুক্তিগুলি
স্ট্যাকওভারফ্লো.

34

এখানে সমস্যা হ'ল আপনি বাশ এবং সুইফ্টের সাথে মেশা এবং মিল করতে পারবেন না। কমান্ড লাইন থেকে কীভাবে সুইফ্ট স্ক্রিপ্টটি চালানো হবে তা আপনি ইতিমধ্যে জানেন, এখন আপনি সুইফটে শেল কমান্ডগুলি কার্যকর করতে পদ্ধতি যুক্ত করতে হবে। প্রাকটিক্যালসউইফ্ট ব্লগ থেকে সংক্ষেপে :

func shell(launchPath: String, arguments: [String]) -> String?
{
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments

    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: String.Encoding.utf8)

    return output
}

নিম্নলিখিত সুইফট কোডটি xcodebuildআর্গুমেন্টগুলি দিয়ে কার্যকর করা হবে এবং তারপরে ফলাফল আউটপুট করবে।

shell("xcodebuild", ["-workspace", "myApp.xcworkspace"]);

ডিরেক্টরি বিষয়বস্তুগুলি অনুসন্ধান করার জন্য (যা lsবাশের ক্ষেত্রে যা হয় ), আমি NSFileManagerবাশ আউটপুটের পরিবর্তে সরাসরি সুইফটে ডিরেক্টরিটি ব্যবহার এবং স্ক্যান করার পরামর্শ দিচ্ছি , যা পার্স করতে ব্যথা হতে পারে।


4
দুর্দান্ত - আমি এই সংকলনটি করতে কয়েকটি সম্পাদনা করেছি, তবে আমি অনুরোধ করার চেষ্টা করার সময় আমি রানটাইম ব্যতিক্রম পাচ্ছি shell("ls", [])- 'NSInvalidArgumentException', reason: 'launch path not accessible' কোনও ধারণা?
রবার্ট

4
এনএসটিস্ক শেকের মতো কার্যনির্বাহী (পরিবেশ থেকে আপনার PATH ব্যবহার করে) অনুসন্ধান করে না । লঞ্চের পথটি অবশ্যই একটি পরম পাথ (যেমন "/ bin / ls") বা বর্তমান কার্যনির্বাহী ডিরেক্টরি সম্পর্কিত একটি পাথ হতে হবে।
মার্টিন আর

stackoverflow.com/questions/386783/… পাঠ মূলত শেলের ধারণা এবং পৌঁছনীয় নয়।
লেগোলেস

দুর্দান্ত - এটি এখন কাজ করে। আমি সম্পূর্ণ স্ক্রিপ্ট + সম্পূর্ণতার জন্য কয়েকটি পরিবর্তন পোস্ট করেছি। ধন্যবাদ.
রবার্ট

4
শেল ("সিডি", "~ / ডেস্কটপ /") ব্যবহার করে আমি পেয়েছি: / usr / bin / cd: লাইন 4: সিডি: ~ / ডেস্কটপ /: এ জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই
জাপোরোঝেঙ্কো ওলেকসান্দ্র

22

সুইচ 3.0 এ ইউটিলিটি ফাংশন

এটিও কার্য সমাপ্তির স্থিতি ফিরিয়ে দেয় এবং সমাপ্তির জন্য অপেক্ষা করে।

func shell(launchPath: String, arguments: [String] = []) -> (String? , Int32) {
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments

    let pipe = Pipe()
    task.standardOutput = pipe
    task.standardError = pipe
    task.launch()
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8)
    task.waitUntilExit()
    return (output, task.terminationStatus)
}

4
import Foundationনিখোঁজ
বিনিয়েনার

4
দুঃখের বিষয়, আইওএসের জন্য নয়।
রাফেল

17

আপনি যদি কমান্ড কল করার জন্য বাশ পরিবেশ ব্যবহার করতে চান তবে নীচের ব্যাশ ফাংশনটি ব্যবহার করুন যা লেগোলেসের একটি স্থির সংস্করণ ব্যবহার করে। শেল ফাংশনের ফলাফল থেকে আমাকে একটি চলন্ত নিউলাইনটি সরিয়ে ফেলতে হয়েছিল।

সুইফট 3.0: (এক্সকোড 8)

import Foundation

func shell(launchPath: String, arguments: [String]) -> String
{
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments

    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: String.Encoding.utf8)!
    if output.characters.count > 0 {
        //remove newline character.
        let lastIndex = output.index(before: output.endIndex)
        return output[output.startIndex ..< lastIndex]
    }
    return output
}

func bash(command: String, arguments: [String]) -> String {
    let whichPathForCommand = shell(launchPath: "/bin/bash", arguments: [ "-l", "-c", "which \(command)" ])
    return shell(launchPath: whichPathForCommand, arguments: arguments)
}

উদাহরণস্বরূপ বর্তমান ওয়ার্কিং ডিরেক্টরিটির বর্তমান ওয়ার্কিং গিট শাখা পেতে:

let currentBranch = bash("git", arguments: ["describe", "--contains", "--all", "HEAD"])
print("current branch:\(currentBranch)")

13

লেগোলেস এর উত্তরের ভিত্তিতে সম্পূর্ণ স্ক্রিপ্ট

#!/usr/bin/env swift

import Foundation

func printShell(launchPath: String, arguments: [String] = []) {
    let output = shell(launchPath: launchPath, arguments: arguments)

    if (output != nil) {
        print(output!)
    }
}

func shell(launchPath: String, arguments: [String] = []) -> String? {
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments

    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: String.Encoding.utf8)

    return output
}

// > ls
// > ls -a -g
printShell(launchPath: "/bin/ls")
printShell(launchPath: "/bin/ls", arguments:["-a", "-g"])

11

অ্যাপল .launchPath এবং লঞ্চ () উভয়কে অবজ্ঞা করেছে, কেবল এটি আপডেট করার জন্য, এখানে সুইফট 4-এর জন্য একটি আপডেটেড ইউটিলিটি ফাংশন যা সামান্য আরও ভবিষ্যতের প্রমাণ হওয়া উচিত।

দ্রষ্টব্য: প্রতিস্থাপনগুলিতে অ্যাপলের ডকুমেন্টেশন ( রান () , এক্সিকিউটেবল ইউআরএল , ইত্যাদি) মূলত এই মুহুর্তে খালি।

import Foundation

// wrapper function for shell commands
// must provide full path to executable
func shell(_ launchPath: String, _ arguments: [String] = []) -> (String?, Int32) {
  let task = Process()
  task.executableURL = URL(fileURLWithPath: launchPath)
  task.arguments = arguments

  let pipe = Pipe()
  task.standardOutput = pipe
  task.standardError = pipe

  do {
    try task.run()
  } catch {
    // handle errors
    print("Error: \(error.localizedDescription)")
  }

  let data = pipe.fileHandleForReading.readDataToEndOfFile()
  let output = String(data: data, encoding: .utf8)

  task.waitUntilExit()
  return (output, task.terminationStatus)
}


// valid directory listing test
let (goodOutput, goodStatus) = shell("/bin/ls", ["-la"])
if let out = goodOutput { print("\(out)") }
print("Returned \(goodStatus)\n")

// invalid test
let (badOutput, badStatus) = shell("ls")

এটি কার্যকর হয়ে দেখার জন্য এটি সরাসরি কোনও খেলার মাঠে আটকানোতে সক্ষম হওয়া উচিত।


8

সুইফট ৪.০ এর জন্য আপডেট করা হচ্ছে (পরিবর্তনের সাথে সম্পর্কিত String)

func shell(launchPath: String, arguments: [String]) -> String
{
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments

    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: String.Encoding.utf8)!
    if output.count > 0 {
        //remove newline character.
        let lastIndex = output.index(before: output.endIndex)
        return String(output[output.startIndex ..< lastIndex])
    }
    return output
}

func bash(command: String, arguments: [String]) -> String {
    let whichPathForCommand = shell(launchPath: "/bin/bash", arguments: [ "-l", "-c", "which \(command)" ])
    return shell(launchPath: whichPathForCommand, arguments: arguments)
}


4

এখানে পোস্ট করা কয়েকটি সমাধানের চেষ্টা করার পরে আমি দেখতে পেলাম যে আদেশগুলি কার্যকর করার সর্বোত্তম উপায়টি -cআর্গুমেন্টগুলির জন্য পতাকা ব্যবহার করা হয়েছিল।

@discardableResult func shell(_ command: String) -> (String?, Int32) {
    let task = Process()

    task.launchPath = "/bin/bash"
    task.arguments = ["-c", command]

    let pipe = Pipe()
    task.standardOutput = pipe
    task.standardError = pipe
    task.launch()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8)
    task.waitUntilExit()
    return (output, task.terminationStatus)
}


let _ = shell("mkdir ~/Desktop/test")

0

সুইফ্ট 3 এর জন্য রিন্টারো এবং লেগোলেস এর উত্তরগুলি মিশ্রিত করা

@discardableResult
func shell(_ args: String...) -> String {
    let task = Process()
    task.launchPath = "/usr/bin/env"
    task.arguments = args

    let pipe = Pipe()
    task.standardOutput = pipe

    task.launch()
    task.waitUntilExit()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()

    guard let output: String = String(data: data, encoding: .utf8) else {
        return ""
    }
    return output
}

0

এনভিভ ভেরিয়েবলের সমর্থন সহ ছোট উন্নতি:

func shell(launchPath: String,
           arguments: [String] = [],
           environment: [String : String]? = nil) -> (String , Int32) {
    let task = Process()
    task.launchPath = launchPath
    task.arguments = arguments
    if let environment = environment {
        task.environment = environment
    }

    let pipe = Pipe()
    task.standardOutput = pipe
    task.standardError = pipe
    task.launch()
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8) ?? ""
    task.waitUntilExit()
    return (output, task.terminationStatus)
}

0

পাইথন স্ক্রিপ্ট চালানোর জন্য প্রক্রিয়া শ্রেণি ব্যবহারের উদাহরণ।

এছাড়াও:

 - added basic exception handling
 - setting environment variables (in my case I had to do it to get Google SDK to authenticate correctly)
 - arguments 







 import Cocoa

func shellTask(_ url: URL, arguments:[String], environment:[String : String]) throws ->(String?, String?){
   let task = Process()
   task.executableURL = url
   task.arguments =  arguments
   task.environment = environment

   let outputPipe = Pipe()
   let errorPipe = Pipe()

   task.standardOutput = outputPipe
   task.standardError = errorPipe
   try task.run()

   let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
   let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()

   let output = String(decoding: outputData, as: UTF8.self)
   let error = String(decoding: errorData, as: UTF8.self)

   return (output,error)
}

func pythonUploadTask()
{
   let url = URL(fileURLWithPath: "/usr/bin/python")
   let pythonScript =  "upload.py"

   let fileToUpload = "/CuteCat.mp4"
   let arguments = [pythonScript,fileToUpload]
   var environment = ProcessInfo.processInfo.environment
   environment["PATH"]="usr/local/bin"
   environment["GOOGLE_APPLICATION_CREDENTIALS"] = "/Users/j.chudzynski/GoogleCredentials/credentials.json"
   do {
      let result = try shellTask(url, arguments: arguments, environment: environment)
      if let output = result.0
      {
         print(output)
      }
      if let output = result.1
      {
         print(output)
      }

   } catch  {
      print("Unexpected error:\(error)")
   }
}

আপনি "আপলোড.পিআই" ফাইলটি কোথায় রাখবেন
সুহাইব রোমি

0

আমি সুইফটেক্সেক তৈরি করেছি , এই জাতীয় কমান্ড চালানোর জন্য একটি ছোট গ্রন্থাগার:

import SwiftExec

var result: ExecResult
do {
    result = try exec(program: "/usr/bin/git", arguments: ["status"])
} catch {
    let error = error as! ExecError
    result = error.execResult
}

print(result.exitCode!)
print(result.stdout!)
print(result.stderr!)

এটি একটি একক-ফাইল লাইব্রেরি যা সহজেই প্রকল্পগুলিতে অনুলিপি-আটকানো যায় বা এসপিএম ব্যবহার করে ইনস্টল করা যায়। এটি পরীক্ষা করা হয়েছে এবং ত্রুটি পরিচালনা পরিচালনা সহজ করে।

শেলআউট এছাড়াও রয়েছে , যা অতিরিক্তভাবে বিভিন্ন পূর্বনির্ধারিত কমান্ডকে সমর্থন করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.