Exécution de commande externe avec swift

Exécution de commande externe avec swift

Si vous écrivez #! / Usr / bin / swift dans la tête

chmod a+x hoge.swift
./hoge.swift #swift hoge.Peut également être démarré avec swift

Je savais que cela pouvait être lancé comme un script, donc après avoir étudié, j'ai traduit le script perl que j'avais sous la main en swift. Une note à ce moment-là.

perl

my $status = system "ls hoge/"  #ret-code
my $ret = `ls hoge/ `           #output

Comment dois-je écrire cela en swift? Je l'ai cherché.

Appel simple

Je n'ai écrit aucune application OSX, donc je ne les ai pas utilisées, mais sur NSTask Je pense que je peux le faire. Vous pouvez recevoir la sortie des commandes externes avec task.standardOutput (NSPipe). Si vous souhaitez spécifier le répertoire courant et l'exécuter, définissez-le sur task.currentDirectoryPath.

func stdOutOfCommand(cmd: String, arguments args: [String], currentDirPath currentDir: String? = nil) -> String {
    let task: NSTask = NSTask()
    task.launchPath = cmd
    task.arguments = args
    if currentDir != nil { task.currentDirectoryPath = currentDir! }
    let pipe: NSPipe = NSPipe()
    task.standardOutput = pipe
    task.launch()
    let out: NSData = pipe.fileHandleForReading.readDataToEndOfFile()
    let outStr: String? = NSString(data: out, encoding: NSUTF8StringEncoding) as? String
    return outStr == nil ? "" : outStr!
}

var ret = stdOutOfCommand("/bin/ls", arguments: ["hoge/"])

Interactif

Dans le format interactif (nécessite une entrée), utilisez waitForDataInBackgroundAndNotify () pour notifier qu'il s'agit d'une attente en arrière-plan. NSNotificationCenter doit recevoir «NSFileHandleDataAvailableNotification».

Si vous voulez attendre la fin de la tâche, attendez avec task.waitUntilExit (). Le statut de fin peut être obtenu avec task.terminationStatus.

Dans l'exemple ci-dessous, l'entrée est contrôlée à l'aide de NSFileHandle.fileHandleWithStandardInput ().

func printFlush(message: String) {
    print(message, terminator: "")
    fflush(__stdoutp)
}
func scriptWithCmd(cmd: String, arguments args: [String], currentDirPath currentDir: String? = nil) -> Int32 {
    //set task
    let input: NSFileHandle = NSFileHandle.fileHandleWithStandardInput()
    let inPipe: NSPipe = NSPipe()
    let outPipe: NSPipe = NSPipe()
    let task: NSTask = NSTask()
    task.launchPath = cmd
    task.arguments = args
    if currentDir != nil { task.currentDirectoryPath = currentDir! }
    task.standardOutput = outPipe
    task.standardInput = inPipe
    task.launch()
    
    //notification
    input.waitForDataInBackgroundAndNotify()
    outPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
    NSNotificationCenter.defaultCenter().addObserverForName(NSFileHandleDataAvailableNotification, object: input, queue: nil,
        usingBlock : { (notification: NSNotification!) in
            let inData: NSData = input.availableData
            if inData.length > 0 {
                inPipe.fileHandleForWriting.writeData(inData)
                input.waitForDataInBackgroundAndNotify()
            } else {
                inPipe.fileHandleForWriting.closeFile()
            }
        }
    )
    NSNotificationCenter.defaultCenter().addObserverForName(NSFileHandleDataAvailableNotification, object: outPipe.fileHandleForReading, queue: nil,
        usingBlock:  { (notification: NSNotification!) in
            let outData: NSData = outPipe.fileHandleForReading.availableData
            if let outStr: NSString = NSString(data: outData, encoding: NSUTF8StringEncoding) {
                printFlush(outStr as String)
            }
            outPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
        }
    )
    
    task.waitUntilExit()
    return task.terminationStatus
}

Mémo simple pour appeler des commandes externes dans d'autres langues

Celui sur lequel j'ai fait une petite recherche avant

Perl

Il y a aussi ʻexec () , mais il ne revient pas, alors utilisez system () `. Retour de devis pratique.

my $status = system "ls hoge/"  #ret-code
my $ret = `ls hoge/ `           #output

C

Auparavant, perl était trop lent, donc une note lorsque j'essayais de faire diverses choses avec C / C ++

#include <stdlib.h>
	int ret = system("ls hoge/");

Avec POSIX, vous pouvez utiliser popen / pclose.

#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#define BUF 256
int main (void) {
	FILE *fp;
	char buf[BUF];
	char *cmd = "/bin/ls hoge/";
	
	if ((fp=popen(cmd,"r")) == NULL) {
		err(EXIT_FAILURE, "%s", cmd);
	}
	while(fgets(buf, BUF, fp) != NULL) {
		fputs(buf, stdout);
	}
	pclose(fp);

	return 0;
}

Puisque popen ne peut pas entrer et sortir en même temps, il est nécessaire d'utiliser autour de pipe (), dup (), fork (), ʻexec * () `.

Référence

C++

PStreams (POSIX) semble être utilisable

Java

Il semble utiliser ProcessBuilder, Les commandes que le shell interprète directement peuvent-elles être exécutées directement?

référence

JavaScript(Node.js)

execSync = require("child_process").execSync;
result = execSync("ls");

référence

Recommended Posts

Exécution de commande externe avec swift
Premiers pas avec Swift
À partir de Swift Swift UI
Changer Wordpress siteurl avec la commande
Comparez Java 8 en option avec Swift
Comment exécuter la commande de copie Postgresql avec des informations de colonne sur Java
Exécuter du code Java packagé avec des commandes
Créer une application en ligne de commande avec maven
Mémo de débogage Xcode pour débutant Swift