如何在 macOS 上编写带空格的 Bash 脚本别名

3

更新:

我有所进展,但仍不确定自己没有理解的是什么。我将脚本简化为一行,但仍然遇到同样的问题。

以下内容是否有任何见解?
注意:如果我输入“/Users/Da.../Docker”或者像下面这样使用退格键代替空格,结果都是相同的。

for myvm in $(find /Users/David/Documents/Virtual\ Machines/Docker -name *.vmx); do echo -e "VM name: $myvm"; done VM name: /Users/David/Documents/Virtual VM name: Machines/Docker/RHEL7-DockerHost-Node04.vmwarevm/RHEL7-DockerHost-Node04.vmx ... VM name: /Users/David/Documents/Virtual VM name: Machines/Docker/RHEL7-DockerHost.vmwarevm/RHEL7-DockerHost.vmx VM name: /Users/David/Documents/Virtual VM name: Machines/Docker/RHEL7-DockerHost-Node01.vmwarevm/RHEL7-DockerHost-Node01.vmx

我错过了什么?

--------------------------

我找到了类似的问题,但答案对我不起作用。

我正在编写一个脚本,可以让我在VMware Fusion中启动和停止多个虚拟机,而无需使用“vmrun”命令单击每个虚拟机,该命令位于“/Applications/VMware Fusion.app/Contents/Library/vmrun”。

问题

当我尝试别名vmrun时:

alias myvmcli='/Applications/VMware\ Fusion.app/Contents/Library/vmrun'

我从bash获得以下错误:

第3行:/Applications/VMware\: 没有那个文件或目录

讨论

很明显缺少空格,但我认为使用退格字符应该表明应使用空格。

我尝试在别名行中使用单引号和双引号都没有成功。

如果我从命令行运行alias,它可以正常工作。

解决方案/想法?

我相信创建一个链接可以解决我的问题,但我真的想知道为什么这不起作用。


2
Bash文档指出:“几乎对于所有目的,shell函数优于别名。”这是一个你可以添加到.bashrc中的shell函数,而不是你的别名。添加后,您应该执行souce ~/.bashrc以使其在命令行上可用。 myvmcli() { "/Applications/VMware Fusion.app/Contents/Library/vmrun" ; } - Inian
1
@Inian:我同意你关于别名的观点,但在这种情况下,只需要一个简单的变量赋值即可。 - cdarke
感谢@cdarke。我确实意识到这点(空格是用于解析的分隔符),但在我的循环中忽略了这个事实(认为只要在脚本中要求它不这样做,它就不会这样做)。我“认为”通过使用反斜杠和引号来实现了这一点。你知道如何强制for循环忽略空格作为分隔符吗?如果您想将路径作为命令参数使用(例如我想用vmrun),您认为处理带有空格的路径的最佳方式是什么?再次感谢! - DSpencer
对于for循环,您可以玩弄IFS =(字段内分隔符),但我不建议这样做,除非您真的知道自己在做什么,因为会出现意外的副作用。最好始终引用值(正如您在许多编程语言中必须这样做)-确实没有任何魔法方法可以避免它。我曾经教过bash,只需拥有一个名为'这是一个文件'的文件就能破坏大多数学生的脚本。 - cdarke
感谢您的所有评论和知识,@cdarke! - DSpencer
显示剩余9条评论
3个回答

2

您可以通过将目录添加到路径中来避免使用函数和别名:

PATH="/Applications/VMware Fusion.app/Contents/Library:$PATH"

然后只需使用vmrun即可。


1

你需要引用两次:

alias myvmcli='"/Applications/VMware Fusion.app/Contents/Library/vmrun"'

或者转义:

alias myvmcli=\''/Applications/VMware Fusion.app/Contents/Library/vmrun'\'

或者

alias myvmcli="\"/Applications/VMware Fusion.app/Contents/Library/vmrun\""

注意第二个和第三个的转义方式不同。


你需要使用双引号,因为别名命令 (alias asd="echo asd") 需要引用一次,而别名内部的命令也需要引用一次。


编辑:

虽然我回答了这个问题,但你发布的别名对我来说完全正常。可能是由于bash版本的差异造成的:

[  0][s: ~ ]$ cd /tmp
[  0][s: tmp ]$ alias asd='asd\ zxc/test'
[  0][s: tmp ]$ asd
woooo!

如果在select语句中使用变量会发生什么?这就是我遇到问题的地方(使用macOS 10.13 bash 3.2.57(1)-release)。当我将赋值移到select之前时,行为发生了变化。它仍然没有按预期工作,所以我正在寻找其他选项。谢谢! - DSpencer

1

在引号内不需要反斜杠\,它会被保留。只有当你不使用引号时才需要反斜杠,但通常使用引号更好。

$ echo 'Hello\ world'
Hello\ world
$ echo "Hello\ world"
Hello\ world
$ echo Hello\ world
Hello world
$ echo "Hello world"
Hello world

在脚本中使用别名并不好,别名真正的设计目的是作为命令行上的生产力辅助工具。在这种情况下,只需将其分配给一个变量即可,您不需要别名或函数。
cmd='/Applications/VMware Fusion.app/Contents/Library/vmrun'

然后,当您想要运行它时:

"$cmd"

注意双引号,因为有嵌入空格。
在OS X上使用vmware测试过。
正如其他人所说,比这更复杂的内容需要一个函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接