Why does this command behave differently depending on whether it's called from terminal.app or a scala program?

感情迁移 提交于 2021-01-29 05:39:22

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!