bash 脚本中的 ls 出现问题

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

答案1

这里有两个问题。第一个是引用。你应该养成这样的习惯总是引用你的变量。有关这方面的更多信息,请参阅:

然而,这并不是真正破坏你的脚本的原因。下一个问题来自于您尝试解析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"

相关内容