2014-02-05 31 views
0

當我使用/ bin/sh的我可以簡單地通過回它通過發出命令慶典語法錯誤,當我嘗試使用bash從sh`echo'rm -rf!(cookbooks)'| bash`

[email protected]:~$ sh 
$ echo 'ls' | bash 
some.sh 

但是當我嘗試使用此命令rm -rf !(cookbooks)我得到這個

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

我需要從/ bin/sh發出這個命令。從封隔器http://www.packer.io/提供腳本

if [ -d "/opt/chef/chef-solo/" ]; then 
    cd /opt/chef/chef-solo 
    rm -rf !(cookbooks) 
fi 
+0

什麼是你想在這裏做什麼? – anubhava

+0

...實際上,我意識到(相當遲到)簡單的解決方案就是使用find,而不是依賴bashisms *或* POSIX sh扭曲。 –

+0

由於'--delete'選項是對'find'的GNU擴展,所以使用它將會與bashism相媲美。 – chepner

回答

6

!(cookbooks)

@anubhava是extglob。它們並未默認啓用;您需要在前一行bash中運行shopt -s extglob(因爲解析器逐行運行)才能使其生效。

所以:

printf '%s\n' 'shopt -s extglob' 'rm -rf !(cookbooks)' | bash 

...或者你可以啓用通過命令行extglobs(感謝chepner的附錄):

echo 'rm -rf !(cookbooks)' | bash -O extglob 

順便說一句,這是可能在POSIX sh中執行此操作,而不使用extglobs。例如:

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

...或者,更簡單,只需使用find:

find . -mindepth 1 -maxdepth 1 -name cookbooks -prune -o -exec rm -rf '{}' + 
+2

當你用'bash -O extglob'啓動'bash'時,你可以啓用'extglob'。 – chepner

+0

@chepner,謝謝 - 編輯它在。 –

+0

和GNU發現有--delete動作內置 – Basilevs