如何在scala sys.process调用上获得shell扩展

如何在scala sys.process调用上获得shell扩展,scala,process,expansion,Scala,Process,Expansion,考虑一个简单的shell扩展尝试: 简单/直接方法: scala> ("/bin/ls /tmp/*" run BasicIO(false, sb, None)).exitValue ls: /tmp/*: No such file or directory res18: Int = 1 scala> ("bash -c \"/bin/ls /tmp/*\"" run BasicIO(false, sb, None)).exitValue /tmp/*": -c: line 0:

考虑一个简单的shell扩展尝试:

简单/直接方法

scala> ("/bin/ls /tmp/*" run BasicIO(false, sb, None)).exitValue
ls: /tmp/*: No such file or directory
res18: Int = 1
scala> ("bash -c \"/bin/ls /tmp/*\"" run BasicIO(false, sb, None)).exitValue
/tmp/*": -c: line 0: unexpected EOF while looking for matching `"'
/tmp/*": -c: line 1: syntax error: unexpected end of file
res19: Int = 2
scala> ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
<console>:1: error: ';' expected but ')' found.
       ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
我已经尝试了ProcessIO、BasicIO、Process等多种组合,但不知道如何让shell扩展工作

bash-c

scala> ("/bin/ls /tmp/*" run BasicIO(false, sb, None)).exitValue
ls: /tmp/*: No such file or directory
res18: Int = 1
scala> ("bash -c \"/bin/ls /tmp/*\"" run BasicIO(false, sb, None)).exitValue
/tmp/*": -c: line 0: unexpected EOF while looking for matching `"'
/tmp/*": -c: line 1: syntax error: unexpected end of file
res19: Int = 2
scala> ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
<console>:1: error: ';' expected but ')' found.
       ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
管道到bash-s

scala> ("/bin/ls /tmp/*" run BasicIO(false, sb, None)).exitValue
ls: /tmp/*: No such file or directory
res18: Int = 1
scala> ("bash -c \"/bin/ls /tmp/*\"" run BasicIO(false, sb, None)).exitValue
/tmp/*": -c: line 0: unexpected EOF while looking for matching `"'
/tmp/*": -c: line 1: syntax error: unexpected end of file
res19: Int = 2
scala> ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
<console>:1: error: ';' expected but ')' found.
       ("echo \"/bin/ls /tmp/*\" | bash -s") run BasicIO(false, sb, None)).exitValue
理解wrt scala进程类也会对Shell转义感兴趣:一个同时包含扩展和转义的示例是最佳的

更新我找到了这个JIRA-可能与此相关。我希望不是-这意味着这里描述的功能几乎没有希望

sys.process.\uu在它可以接受的内容方面限制太多,无法使用

另一次更新我发现了一封旧邮件,其中涉及尊敬的丹尼尔·索布拉尔,他提到:

因为引号没有分隔传递给bash的参数-- 是Scala决定了争论的破裂方式,这很简单 在空格上拆分,没有任何报价工具。如果你试一下 相反,它将发挥以下作用:

Seq(“bash”、“-c”、“ls*.scala”)

对于运行shell命令的“开火并忘记”版本来说,情况看起来更加严峻。我渴望红宝石

 %x{whatever shell string you want goes here}
e、 g

echo“打印%x{ls-lrtad/etc/*2>&1}”ruby

最令人满意的回报是:

-r--r--r--   1 root   wheel          69836 May 28  2013 /etc/php.ini.default-

5.2-previous~orig
lrwxr-xr-x   1 root   wheel             30 Oct 22  2013 /etc/localtime -> /usr/share/zoneinfo/US/Pacific
-rw-r--r--   1 root   wheel            102 Nov  5  2013 /etc/hostconfig
-rw-r--r--   1 root   wheel           1286 Nov  5  2013 /etc/my.cnf
-rw-r--r--   1 root   wheel           4161 Dec 18  2013 /etc/sshd_config~previous
-rw-r--r--   1 root   wheel            199 Feb  7  2014 /etc/shells
-rw-r--r--   1 root   wheel              0 Sep  9  2014 /etc/xtab
-rw-r--r--   1 root   wheel           1316 Sep  9  2014 /etc/ttys
  .. etc

但看起来Scala没有出现这种情况。

我担心你误解了我的答案。Ruby也在做同样的事情,我不看他们的代码就知道这一点,因为Java(以及Scala)作为API提供的是Unix API的直接翻译

是shell进行了shell扩展,尽管任何其他软件都完全有可能模仿它们,但这将是一场失败的游戏。通常会提供通配符,但它们只是shell扩展的一小部分

我的答案有你需要的一切,但让我进一步说明:

import scala.sys.process._
implicit class RubyX(val sc: StringContext) extends AnyVal {
  def x(args: Any*): ProcessBuilder = {
    val strings = sc.parts.iterator
    val expressions = args.iterator
    var buf = new StringBuffer(strings.next)
    while(strings.hasNext) {
      buf append expressions.next
      buf append strings.next
    }
    Process(Seq("bash", "-c", buf.toString))
  }
}
那你就可以了

x"ls *.scala".!

我返回了一个ProcessBuilder,因此您可以选择适合您的最佳执行形式,例如
返回退出代码,并将所有其他内容回显到stdout。

哦,我认为现在重要的一点是,我们只需要三个部分来完成流程(.)调用。考虑到整个命令行是三个部分中的一个,这很好。是的,我错误地收集到命令行的每一部分都需要是流程调用的不同成员。这里仍然缺少一些东西:scala>Process(Seq(“bash”、“-C”、“ls/tmp/*”)。!!bash:ls/tmp/*:没有此类文件或directory@javadba小写
-c
.ah man。。但愿你早点注意到这一点。刚刚花了两个小时尝试将java.lang.Process代码(以及相关的流读取器/写入器)转换为scala。但这很好——而且简单得多。所以最后一切都好。。