Linux
bash 腳本中的 ls 問題
基本上我試圖遞歸地列出子目錄,直到我找到一個沒有更多目錄的目錄。這裡的問題是,當我將參數傳遞給函式時,正如給出的那樣,ls 命令不起作用。如果沒有引號中的 $var, ls 會將空格分隔的字元串視為多個參數。
為什麼會發生這種情況,我該如何避免?
#! /bin/bash function subdir_check(){ local var="$*" ls -F -b "$var" | grep '/' | sed 's/\///g' } directory="$1" if [[ $(subdir_check $directory) != "" ]] then pick=$(subdir_check $directory | rofi -dmenu -p 'Select Subdirectory') directory="${directory}/${pick}" while [[ $(subdir_check $directory) != "" ]] do pick=$(subdir_check $directory | rofi -dmenu -p 'Select Subdirectory') directory="${directory}/${pick}" done fi echo $directory
這裡有兩個問題。首先是引用。你應該養成總是引用變數的習慣。有關這方面的更多資訊,請參閱:
但是,這並不是真正破壞您的腳本的原因。下一個問題來自您嘗試解析
ls
. 為什麼這是一個壞主意,請參閱:具體來說,這裡的問題是您使用
-b
它會導致名為的目錄dir one
顯示為dir\ one
. 如果您從菜單選擇器中選擇它,那麼您將subdir_check
作為dir\ one
參數執行。因為這是引用的(var
在函式中被引用),所以您試圖ls
在文字上執行dir\ one
,因為您在引用,所以轉義的空間不會被讀取為被轉義。但是,如果您不引用它,它將被視為兩個單獨的參數。所以整個事情有點混亂。這是您的腳本的工作版本,使用您的基本方法並稍作調整:
#! /bin/bash function subdir_check(){ ## globs that don't match anything should expand to the empty string ## instead of expanding to the glob itself as happens by default shopt -s nullglob ## save all sub directories in the 'dirs' array local dirs=("$@"/*/); ## Print each dir on its own line and remove the trailing '/'. printf '%s\n' "${dirs[@]}" | sed 's|/$||' } ## Remove the trailing '/' from the input. directory=$(sed 's|/$||'<<<"$1") ## Quote all the things! if [[ $(subdir_check "$directory") != "" ]] then ## You don't need a second variable. Just one: directory. This will now ## include the path. directory=$(subdir_check "$directory" | rofi -dmenu -p 'Select Subdirectory') while [[ $(subdir_check "$directory") != "" ]] do directory=$(subdir_check "$directory" | rofi -dmenu -p 'Select Subdirectory') done fi echo "$directory"