基本上我试图递归地列出子目录,直到找到一个没有更多目录的目录。这里的问题是,当我将参数传递给函数时,如给定的那样, 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"