众所周知,解析 ls 的输出是一般来说是个坏主意一种解决方案是使用 globbing 而不是 ls 来“安全”地循环目录中的文件。
for path in /path/to/search/*; do
...
# Do more filtering
...
echo "$path"
done
该函数会进一步过滤glob匹配的一些结果,并输出剩余的路径。
但是,如果我想在其他地方重用这个逻辑,我可以通过函数安全地使用它的输出并循环它吗?
function myglob() {
for path in /path/to/search/*; do
...
# Do more filtering
...
echo "$path"
done
}
function myExample() {
results=$(myglob)
for i in "$results"; do
echo "$i"
done
}
或者我必须始终复制全局逻辑并对内部逻辑进行较小的更改?
答案1
不,您不能重复使用您所显示的循环输出,因为它完全复制了问题ls
,并且增加了echo
可能解释文件名中的反斜杠的问题。
相反,如果您使用具有数组和名称引用的 shell 语言(如bash
4.3+ 中),则可以稍微不同地执行此操作:
myglob () {
declare -n list="$1"
list=( /path/to/search/* )
}
myexample () {
local results=()
myglob results
for pathname in "${results[@]}"; do
printf '%s\n' "$pathname"
done
# or shorter, just
# printf '%s\n' "${results[@]}"
}
这里,该myglob
函数采用 中变量的名称list
,这是一个名称引用变量。这意味着任何使用list
实际上都会使用命名变量。该函数只是扩展 glob 并将结果存储在其中,list
就好像它是一个数组一样。
然后该myexample
函数myglob
使用字符串进行调用results
。因此, list
in 中的变量将myglob
引用该results
变量,并将扩展模式存储在其中。
然后该函数继续用作results
项目数组。
如果myglob
需要做过滤:
myglob () {
declare -n list="$1"
list=()
for pathname in /path/to/search/*; do
# decide whether to use "$pathname" or not
# then, if it is to be used,
list+=( "$pathname" )
done
}
也就是说,如果要将项目返回给调用者,则循环扩展模式并将项目附加到列表中。