如何轻松计算包含空格的路径的全局匹配数?

如何轻松计算包含空格的路径的全局匹配数?

我正在处理带有空格的路径。

我以这种方式进行通配(第二行设置通配):

IFS=$'\n'

VAR="$1/"name_*

for file in $VAR; do
  echo $file
  grep ITEM "$file" | wc -l
done

我只需要查看name_*$1.我IFS在这里设置的值可以让我正确地查看文件,因为它可以防止for文件名中的空格引起错误。

但是,我现在想要一种简单的方法来获取与 glob 匹配的此类文件的总数。我知道我可以在 for 循环中使用计数器,但我希望我可以使用管道来VAR做到这一点。

但是,如果我echo $VAR成功地进行了通配,但是不同的路径通过空格连接起来,这会毁了我,因为我现在无法再分隔这些项目...有没有一种方法可以覆盖这种行为,类似于 IFS 的工作方式for

答案1

如果您想要的是分隔值的列表,您应该避免使用/扩展字符串。

基本的解决方案是设置位置参数:

set -- "$1"/name_*

这会将每个匹配的文件保留在一个单独的位置参数中,即使有空格或换行符(或大多数其他字符)。

在 bash 中,如果 glob ( ) 没有匹配到任何文件,或者如果glob 无法匹配任何文件而您不想得到任何结果(而不是 glob 本身) ,则应该设置shopt -s failglob为使脚本停止。保持failglob 未设置以避免停止脚本。*shopt -s nullglob"$1"/name_*

文件数 (计算 glob 的匹配数) 现在简单地说:

echo "$#"

位置参数的计数。

for 循环将减少为:

for file
do  echo "$file"
done

这完全避免了分裂的问题IFS

$1请注意,必须引用外部值以避免代码注入。
也应该echo "$file"引用。

也可以将列表分配给数组:

files=( "$1"/name_* )

这将避免破坏位置参数,但会使语法变得更加复杂。数组中元素的个数为:

echo "${#files[@]}"

循环需要一些改变:

for file in "${files[@]}"; do
    echo "$file"
done

答案2

你可以解决空间问题如果您切换到使用数组,则获取计数:

VAR=("$1/"name_*) # make array of filenames matching glob

echo "${#VAR[@]}" # number of elements in array

for file in "${VAR[@]}"; do  # loop over individual elements of array
  echo "$file"
  grep ITEM "$file" -c  # grep can count, wc isn't needed
done

相关内容