2016-07-14 13 views
1

den folgenden Befehl in der REPL Executing:Clojure shell/sh behandelt einzelne Argumente nicht korrekt?

(shell/sh "ls" "-lah" "'resources'") 

gibt die folgende Ausgabe:

{:exit 2, :out "", :err "ls: cannot access 'resources': No such file or directory\n"} 

den gleichen Befehl in der Bash-Shell Ausführen der richtige Ausgabe ergibt, die Liste der Dateien im Verzeichnis resources . Nach meinem Verständnis bedeutet dies, dass shell/sh nicht in der Lage ist, mit einfachen Anführungszeichen versehene Argumente korrekt zu behandeln. Ist das wahr oder mache ich etwas falsch?

Das obige Beispiel ist ein einfaches Beispiel, da ich normalerweise den Ordnernamen nicht einfach angeben muss. Aber warum ist das ein echtes Problem, weil ich versuche, Audiodateien zu konaktieren, indem ich den folgenden ffmpeg-Befehl mit shell/sh ausführe;

ffmpeg -i resources/ffmpeg_working/1.flac 
-i resources/ffmpeg_working/2.flac 
-i resources/ffmpeg_working/3.flac 
-i resources/ffmpeg_working/4.flac 
-filter_complex '[0:0][1:0][2:0][3:0]concat=n=4:v=0:a=1[out]' 
-map '[out]' 
resources/ffmpeg_working/done.flac 

Dies ergibt die folgende Ausgabe

Stream map ''[out]'' matches no streams. 

Noch einmal, wenn ich die gleiche ffmpeg-Befehl in der Bash ausführen Shell es verkettet die Dateien erfolgreich. Daher scheint es, dass das Argument mit einem einzelnen Anführungszeichen nicht korrekt behandelt wird.

Antwort

3

Quoting ist eine Shell-Funktion, um Shell-Erweiterungen zu vermeiden, die sonst als Platzhalter, Variablen usw. interpretiert würden. Wenn Sie etwas anderes als die Shell verwenden, z. B. Clojure/Java-Prozessmanagement-Tools, gibt es keine Ding als Wildcards oder Variablen, und so etwas wie das Zitieren nicht.

+0

Danke für die Antwort! Bedeutet es also, dass es unmöglich ist, Shell-Befehle auszuführen, die * einfach zitierte Argumente benötigen? – Jarzka

+0

Sie haben die Antwort vollständig falsch verstanden. Sie führen überhaupt keinen Shell-Befehl aus, Sie führen ein Programm wie mit ['EXEC (3)'] (http://linux.die.net/man/3/exec) aus. Du kannst Dinge nicht zitieren, weil du nie etwas zitieren musst. – amalloy

+0

Nach dieser Seite https://trac.ffmpeg.org/wiki/Concatenate "sind die einfachen Anführungszeichen um den gesamten Filterabschnitt erforderlich." und deshalb muss ich sie zitieren. – Jarzka

3

Wie amalloy erwähnt, sollten Sie keine einfachen Anführungszeichen um resources verwenden. Vergleichen Sie mit & ohne:

(require '[clojure.java.shell :as shell]) 
;=> nil 
(shell/sh "ls" "-lah" "'resources'") 
;=> {:exit 2, :out "", :err "ls: cannot access 'resources': No such file or directory\n"} 
(shell/sh "ls" "-lah" "resources") 
;=> {:exit 0, :out "total 8.0K\ndrwxrwxr-x 2 alan alan 4.0K Nov 4 2015 .\ndrwxrwxr-x 8 alan alan 4.0K Jul 14 10:25 ..\n", :err ""} 

Bitte beachten Sie, dass Sie keine Schale überhaupt ausgeführt werden; Sie sprechen direkt mit dem Unix-Kernel, so dass keine Platzhaltererweiterung auftritt. Zum Beispiel sucht der folgende Befehl für eine Datei mit dem Namen * (Stern), gibt es keine Schale den * Charakter als Code zu interpretieren, dass „jede passende Datei“ bedeutet:

(shell/sh "ls" "-l" "*") 
;=> {:exit 2, :out "", :err "ls: cannot access *: No such file or directory\n"} 

Wenn Sie Ihren Befehl haben,

(require '[tupelo.misc :as tm]) 
nil 
clj.core=> (tm/shell-cmd "ls -l *") 
{:exit 0, :out "-rw-rw-r-- 1 alan alan 11218 Nov 4 2015 LICENSE\n-rw-rw-r-- 1 alan alan 16 Jul 12 17:59 my-file.txt\n-rw-rw-r-- 1 alan alan 520 Jan 25 08:29 project.clj\n-rw-rw-r-- 1 alan alan 457 Nov 4 2015 README.md\n-rw-rw-r-- 1 alan alan 4975 Nov 4 2015 tmp.txt\n\ncheckouts:\ntotal 0\nlrwxrwxrwx 1 alan alan 17 Dec 7 2015 tupelo -> /home/alan/tupelo\n\ndoc:\ntotal 4\n-rw-rw-r-- 1 alan alan 101 Nov 4 2015 intro.md\n\nresources:\ntotal 0\n\nsrc:\ntotal 4\ndrwxrwxr-x 2 alan alan 4096 Feb 4 16:28 clj\n\ntarget:\ntotal 4\ndrwxrwxr-x 4 alan alan 4096 Jul 14 10:25 base+system+user+dev\n\ntest:\ntotal 4\ndrwxrwxr-x 3 alan alan 4096 Dec 7 2015 tst\n", :err ""} 

Beachten Sie, dass shell-cmd akzeptiert nur einen einzelnen String-Argument, das gerade an die Shell übergeben wird, nicht mehrere Argumente wie: von der Shell interpretiert, bevor mit dem Linux-Kernel übergeben wird, wird möglicherweise die shell-cmd Funktion in the Tupelo library nutzen möchten clojure.java.shell/sh.