Shell
在“find -exec”中執行“grep | xargs”時出現空行
我正在嘗試通過
.htaccess
(包含deny from all
)列出被 Apache 阻止的 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
anddirname
獲取包含目錄: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 中沒有。
它失敗了,因為當 grep 不匹配時,您沒有將任何內容傳遞給 xargs。
例如:
find
獲取./.htaccess
並呼叫您的-exec
.- 與文件中的
grep
任何內容都不匹配,因此它不輸出任何內容xargs
在沒有任何參數的情況下啟動dirname
,因此dirname
認為它只是被濫用並顯示其幫助消息。執行此操作的正確方法:
find . -type f -name .htaccess -exec grep -iq '^deny from all$' {} \; -printf '%h\n'
你有這個錯誤:
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