Linux

bash 腳本中的 ls 問題

  • September 7, 2019

基本上我試圖遞歸地列出子目錄,直到我找到一個沒有更多目錄的目錄。這裡的問題是,當我將參數傳遞給函式時,正如給出的那樣,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"

引用自:https://unix.stackexchange.com/questions/539509