2016-07-29 55 views
1

如果我輸入rm *,但想以其他方式運行rm,我想讓bash運行rm -i *。重要的是,我不想在每次使用通配符時運行rm -i,例如rm part*。這裏是盡我所能:如何捕獲「*」作爲bash函數的參數並用於比較

rm() 
{ 
    if [ "$1" == "*" ]; then 
     rm -i * 
    else 
     rm $1 
    fi 
} 

但我知道這將失敗。我知道我想要的比較是^*$,但我不知道如何實現它。

+4

通過執行你的'rm'功能'*'已經擴大了時間。 – Paulpro

+3

問題是'rm'沒有得到'*'作爲參數;它獲得了shell擴展'*'作爲參數的長文件列表。 – chepner

+5

GNU'rm'有一個'-I'選項,只有在刪除超過3個文件時纔會提示你。 – chepner

回答

7

這是從字面上不可能知道你的命令是否在沒有你的shell的配合下用通配符調用。

當你調用rm *(像任何其他命令),在*被替換的文件名的調用之前的列表。因此,當在命令內部時,其被賦予通配符的信息不再存在:$1,$2等已被替換爲通配符擴展到的名稱列表。


這就是說,因爲我們是一個shell函數,我們殼的合作是實際可用:

rm() { 
    local cmd 
    read -r _ cmd < <(HISTTIMEFORMAT=''; history 1) 
    if [[ $cmd = "rm *" ]]; then 
    command rm -i "[email protected]" 
    else 
    command rm "[email protected]" 
    fi 
} 

這是如何工作的?

  • history 1返回shell歷史記錄中最近的命令(前面有一個數字)。
  • read -r _ cmd讀取數入變量_,命令行的其餘部分到所述可變cmd
  • [[ $cmd = "rm *" ]]針對精確串
  • command rm ...運行外部rm命令比較命令,避免遞歸回我們的功能再次。
+0

這可能對某些情況無效。我在shell中導出HISTTIMEFORMAT =「[%F%T]」',並且失敗。可能條件可以改爲'[[$ cmd == *「rm *」]]' – anubhava

+0

不,我不是那個意思。在當前形式中,這個函數沒有運行'rm -i ...',因爲我在''.bashrc'中導出了HISTTIMEFORMAT =「[%F%T]」,導致'history 1'輸出'49370 [2016-07-29 15:42:52] rm *'。這就是爲什麼我建議'[[$ cmd == *「rm *」]]'可能會工作 – anubhava

+1

* facepalm * - 我錯過了'*「rm *」'錨定在最後。是的,這很有道理。 –

1

既然你不知道是否有通配符,爲什麼不檢查參數的數量?

例如:

#!/bin/bash 
rm() { 
    if [ "$#" -gt 1 ]; then 
     echo command rm -i "[email protected]" 
    else 
     echo command rm "[email protected]" 
    fi 
} 
rm a b c 
rm a 
+0

...但你不知道你是否得到了'a',因爲那是'*'所評估的或'a',因爲這是用戶通過的。 –

+2

@CharlesDuffy:的確如此。但我認爲這個用例是警告如果多個文件將被刪除,所以它可能是OP的有效選擇。 – user000001

+0

我完全喜歡解決方案的優雅。它實際上涉及到問題的核心 - 防止我刪除多個文件(或者我輸入的任何數字)。但我認爲實際捕捉命令總體上更安全。儘管偉大的工作! – abalter