在“find -exec”中执行“grep | xargs”时出现空行

在“find -exec”中执行“grep | xargs”时出现空行

我试图列出由 Apache 通过.htaccess(包含deny from all)阻止的 Web 服务器的所有目录。我已经设法获取阻止列表.htaccess,但是当我尝试使用提取目录路径时dirname出现一些错误:

  1. 文件列表.htaccess

    find . -type f -name ".htaccess"
    ./.htaccess
    ./config/.htaccess
    ./files/.htaccess
    ./plugins/webservices/.htaccess
    ./plugins/webservices/scripts/.htaccess
    ./install/mysql/.htaccess
    ./scripts/.htaccess
    ./locales/.htaccess
    
  2. 阻止文件列表.htaccess

    find . -type f -name ".htaccess" -exec sh -c "grep -Eli '^deny from all$' '{}'" \;
    ./config/.htaccess
    ./files/.htaccess
    ./plugins/webservices/scripts/.htaccess
    ./install/mysql/.htaccess
    ./scripts/.htaccess
    ./locales/.htaccess
    
  3. 错误就是错误。与 2. 中的列表相同,但使用xargsdirname来获取包含的目录:

    find . -type f -name ".htaccess" -exec sh -c "grep -Eli '^deny from all$' '{}' | xargs dirname" \;
    dirname: missing operand
    Try dirname --help' for more information
    ./config
    ./files
    dirname: missing operand
    Try dirname --help' for more information
    ./plugins/webservices/scripts
    ./install/mysql
    ./scripts
    ./locales
    
  4. 列表 3 的调试尝试:我们可以看到 2 个空行,其中有 2 个错误:

    find . -type f -name ".htaccess" -exec sh -c "grep -Eli '^deny from all$' '{}' | xargs echo" \;
    
    ./config/.htaccess
    ./files/.htaccess
    
    ./plugins/webservices/scripts/.htaccess
    ./install/mysql/.htaccess
    ./scripts/.htaccess
    ./locales/.htaccess
    

这 2 个空行显然与.htaccess被忽略的 2 个文件匹配,因为它们不包含deny from all.我不明白为什么我在列表 3. 和 4. 中得到这些,但在 2. 中却没有。

答案1

它失败是因为当 grep 不匹配时,您没有将任何内容传递给 xargs。

例如:

  1. find获取./.htaccess并调用您的-exec.
  2. grep与文件中的任何内容都不匹配,因此它不输出任何内容
  3. xargs启动时dirname没有任何参数,因此dirname认为它只是被滥用并显示其帮助消息。

执行此操作的正确方法:

find . -type f -name .htaccess -exec grep -iq '^deny from all$' {} \; -printf '%h\n'

答案2

你有这个错误:

dirname: missing operand. Try dirname --help' for more information

因为dirname缺少操作数(没有任何内容作为参数传递)。发生这种情况是因为grep返回了空结果。

如果您使用的是 GNU ,则当输入为空(不包含任何非空白)时,xargs可以使用-r( ) 来不运行该命令。--no-run-if-empty

为了使其与 BSD 一起工作xargs,您可能需要重写命令以检查输入是否为空并相应地运行命令。或者通过抑制 stderr 来忽略错误,例如:

find . ... -exec sh -c "grep ... | xargs dirname 2> /dev/null || true" ';'

或者您可以使用 while 循环,这样您就可以避免解析空文件或文件名中出现空格问题,例如

find . -type f -name ".htaccess" -print0 | while IFS= read -r -d '' file; do

    grep -Eli '^deny from all$' "$file" | while IFS= read -r -d '' deny_file; do
      dirname "$deny_file"
    done

done

相关内容