当我尝试使用sh`echo'rm -rf!(cookbooks)'|中的bash时出现语法错误 bash`

san*_*ari 1 linux bash shell sh packer

当我使用/ bin/sh时,我只需通过回显就可以通过bash发出命令

vagrant@vagrant:~$ sh
$ echo 'ls' | bash
some.sh
Run Code Online (Sandbox Code Playgroud)

但是当我尝试使用这个命令时,rm -rf !(cookbooks)我得到了这个

$ echo 'rm -rf !(cookbooks)' | bash
bash: line 1: syntax error near unexpected token `('
bash: line 1: `rm -rf !(cookbooks)'
Run Code Online (Sandbox Code Playgroud)

我需要从/ bin/sh发出这个命令.

来自包装工http://www.packer.io/配置脚本的@anubhava

if [ -d "/opt/chef/chef-solo/" ]; then
  cd /opt/chef/chef-solo
  rm -rf !(cookbooks)
fi
Run Code Online (Sandbox Code Playgroud)

Cha*_*ffy 6

!(cookbooks)是一个外展.它们默认不启用; 你需要shopt -s extglob在前一行bash中运行(因为解析器逐行操作)才能使其有效.

所以:

printf '%s\n' 'shopt -s extglob' 'rm -rf !(cookbooks)' | bash
Run Code Online (Sandbox Code Playgroud)

...或者你可以通过命令行启用extglobs(感谢chepner的附录):

echo 'rm -rf !(cookbooks)' | bash -O extglob
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这可以做到这一点POSIX SH,不使用extglobs的.例如:

# wrap in a function to have a separate $@ rather than overriding global
delete_all_but_cookbooks() {
  set --
  for f in *; do
    [ "$f" = "cookbooks" ] || set -- "$@" "$f"
  done
  rm -rf "$@"
}
delete_all_but_cookbooks
Run Code Online (Sandbox Code Playgroud)

...或者,更简单,只需使用find:

find . -mindepth 1 -maxdepth 1 -name cookbooks -prune -o -exec rm -rf '{}' +
Run Code Online (Sandbox Code Playgroud)

  • 使用`bash -O extglob`启动`bash`时可以启用`extglob`. (2认同)