问题
So I'm working on extracting a file.cbz to display it's contents.
I was hoping to go about it with the following code:
println("7z x -y \"" + filePath + "\"" + s" -o$tempLocation")
if (("7z x -y \"" + filePath + "\"" + s" -o$tempLocation").! == 0){ //I would have liked to do the whole thing with string interpolation, but I didn't work. Seems to be this bug https://issues.scala-lang.org/browse/SI-6476
Some(new File(tempLocation))
}else{
println("Something went wrong extracting the file, probably an incorrect path. Path: " + filePath)
null
}
When I compile and run this, I get the following output:
7z x -y "/path/to/file/test.cbz" -o/tmp/CViewer-temporary-storage
ERROR: No more files
"
System ERROR:
Unknown error: -2147024872
7-Zip [64] 15.14 : Copyright (c) 1999-2015 Igor Pavlov : 2015-12-31
p7zip Version 15.14.1 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,4 CPUs x64)
Scanning the drive for archives:
Something went wrong extracting the file, probably an incorrect path. Path: /Users/Matt/learning-scala/learning-GUI/test.cbz
Process finished with exit code 0
When I run the command in terminal.app, it works fine, and I get the following:
Matt$ 7z x -y "/Users/Matt/learning-scala/learning-GUI/test.cbz" -o/tmp/CViewer-temporary-storage
7-Zip [64] 15.14 : Copyright (c) 1999-2015 Igor Pavlov : 2015-12-31
p7zip Version 15.14.1 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,4 CPUs x64)
Scanning the drive for archives:
1 file, 19587584 bytes (19 MiB)
Extracting archive: /path/to/file/test.cbz
--
Path = /path/to/file/test.cbz
Type = Rar
Physical Size = 19587584
Solid = -
Blocks = 33
Multivolume = -
Volumes = 1
Everything is Ok
Files: 33
Size: 20400561
Compressed: 19587584
That seems to be the result when 7z is told to extract an empty directory.
回答1:
You seem to be thinking Scala supports Bash-like syntax and unquoting rules. From what I can tell Scala's ProcessBuilder
doesn't have a syntax for unescaping strings when you call !
on a String
. What it seems to do instead is naively split on whitespace and then execute those pieces as your command. This works well if you don't need to embed any whitespace in your command or if your interpolated variables never include whitespace.
The fix is to use Seq
so that you can define each argument individually, without worrying about escaping or unescaping. So you exec line:
"7z x -y \"" + filePath + "\"" + s" -o$tempLocation").!
becomes
Seq("7z", "x" "-y", filePath, s"-o$tempLocation").!
Note: per scripting best practices you should always use the full path to the command you are executing. For me this would be:
Seq("/usr/local/bin/7z", "x" "-y", filePath, s"-o$tempLocation").!
来源:https://stackoverflow.com/questions/38043354/why-does-this-command-behave-differently-depending-on-whether-its-called-from-t