我试图列出由 Apache 通过.htaccess
(包含deny from all
)阻止的 Web 服务器的所有目录。我已经设法获取阻止列表.htaccess
,但是当我尝试使用提取目录路径时dirname
出现一些错误:
文件列表
.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
阻止文件列表
.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
错误就是错误。与 2. 中的列表相同,但使用
xargs
和dirname
来获取包含的目录: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
列表 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。
例如:
find
获取./.htaccess
并调用您的-exec
.grep
与文件中的任何内容都不匹配,因此它不输出任何内容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