[英]Implementing a simple version of find in a bash script
我有一項任務,要求我創建一個可以采用這些參數的find
版本:
-name
(處理名稱的模式) -type
(f和d) -print
-exec
(並且能夠處理{}
,雖然如果exec
存在,你可以假設它將永遠是最后一個參數,不需要用分號終止。 它還聲明“謂詞可以以任何順序出現,並且隱式短路並在一起。不要處理-o(OR)。” 我也不允許在我的腳本中使用find
。
因此,示例輸入將如下所示:
myfind ~/dirtocheck/ -name '*.o' -type f -print -exec /bin/mv {} ~/.TRASH\;
關於如何完成所有這些,我有幾個問題。
首先,我想知道如何使用遞歸來沿路徑導航。 這是我的函數的偽代碼版本:
recurse_path () {
for i in "$@"; do
# call a function that executes rest of program
if [[ -d "${i}" ]]; then
cd "${i}"
recurse_path $(ls ".")
fi
done
}
其次,我不知道將傳遞多少個參數或者真正如何正確解析它們。 在執行任何可以使這更容易的事情之前,我應該做些什么嗎?
例如,我假設我們有一個'-exec'
參數,我可以接受任何過去,並將其移動到一個數組中執行。 但是我該怎么做呢?
最后,它是什么意思“謂詞可以以任何順序出現,並且隱含地短路並在一起。” 我假設這意味着每件事都必須為下一個執行,但我不知道為什么它們會出現故障?
我會感謝任何幫助,甚至是如何構建它以使其工作的想法。
首先,我想知道如何使用遞歸來沿路徑導航。
您的代碼是一個良好的開端。 為了表現得像find
,我會刪除對cd
的調用,而是總是使用相對於起始目錄的路徑。 這意味着遞歸越深,它們就越長。
另外recurse_path $(ls ".")
是一種編寫recurse_path *
的復雜方法。
其次,我不知道將傳遞多少個參數或者真正如何正確解析它們。
作為提示,您可以編寫一個循環來檢查每次迭代$1
,然后使用shift
在它們被處理后刪除參數,因此$1
指向下一組參數。 例如,如果$1
是-name
,則在$2
處理名稱,然后調用shift 2
。
例如,我假設我們有一個'-exec'參數,我可以接受任何過去,並將其移動到一個數組中執行。 但是我該怎么做呢?
如果你已經使用了基於shift
的方法,那么-exec
的參數自然可以簡單地作為"$@"
。
最后,它是什么意思“謂詞可以以任何順序出現,並且隱含地短路並在一起。” 我假設這意味着每件事都必須為下一個執行,但我不知道為什么它們會出現故障?
你不能假設-name
出現在-type
之前。 它們可能處於任何一種順序,或者它們可能會丟失,甚至可能重復多次。 例如:
myfind ~/dirtocheck/ -name '*.o' -type f
myfind ~/dirtocheck/ -type f -name '*.o'
myfind ~/dirtocheck/ -name 'MyClass*' -name '*.java'
首先:你的遞歸看起來很好。 我唯一需要注意的是, ls
真的不應該以這種方式使用的,因為它的格式輸出。 您需要直接使用shell-glob擴展: recurse_path *
。 (請注意,再見默認情況下將不包括任何開頭.
。請問您的分配地址如何處理“隱藏”的文件? find
,我認為,對待他們通常,這意味着你可能需要打開bash的dotglob
選項。
(另請注意,JohnKugelman的答案提出了一個關於完整路徑的好處。雖然使用cd
仍然可以工作 - 例如,你可以在變量中維護相對路徑。雖然沒有任何理由使用cd
。)
第二:你幾乎肯定會使用shift
來獲取你的論點。 請注意,這會更改您的位置參數變量( $1
, $2
等)以及列表變量( $*
和$@
)。 所以,舉例來說,如果您發現$1
(之后的一定數目的shift
S)是-exec
,那么你就可以shift
一次,和$@
將包含要執行的命令(模數代{}
等)。
第三:是的,短路and
意味着如果不滿足條件,則不評估/測試下一個條件; 您可能會發現閱讀有關短路操作符很有幫助,但這個概念很簡單,聽起來您可能已經理解了它。 我相信“任何訂單”條款意味着您可以在-name
之前使用-type
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.