如何在 Git Bash 中处理文件名中的空格

如何在 Git Bash 中处理文件名中的空格

我编写了以下脚本,在 Windows 7 下的 Git Bash 下运行:

#!/usr/bin/env sh
for logfile in `find -name "*.log" -o -name "*.err" -o -name "*.out"`
do
    echo $logfile
    grep "api/" "$logfile"
done

问题是,当文件名中有空格时,grep 会卡住。我以为双引号应该可以解决这个问题,但它却不配合。

有想法吗?

答案1

解决方案 1

最接近的解决方案是使用find-print0读取输出while read …

find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do
    ...

继续使用"$logfile"引号,就像使用变量时一样。

解决方案 2

另一个解决方案是find根本不使用,而只是让其grep在多个文件上运行:

shopt -s nullglob
shopt -s globstar
grep "api/" **/*.log **/*.err **/*.out

这里,globstar启用目录的递归匹配**。您应该设置nullglob以防止在其中一个文件扩展名不存在时出现错误。

但这仅适用于有限的文件集,因为您可能会达到命令行参数的最大长度。

为什么会发生错误?

你永远不应该在(或,或任何其他输出带空格的文件名的函数)for的输出上运行。阅读findls本文了解有关为什么这是个问题以及如何解决它的更多信息。

简而言之,Bash 使用空格来分割参数。假设您有三个文件,afoo barb,那么该行将计算为:

for logfile in a foo bar b; do

显然,Bash 会设置logfileafoobarb,这不是您想要的。如果您可以手动将输入指定为for,则可以将这些文件名括在引号中以解决问题。

为了自动执行此操作,解决方案是用字符分隔这些文件名NUL(这是选项所做的-print0),然后再次根据该字符拆分输出NUL(这是-d ''inread所做的)。

相关内容