即使给出了开始搜索的路径,shellcheck 也会警告查找输出上的循环

即使给出了开始搜索的路径,shellcheck 也会警告查找输出上的循环

乌班图16.04

#!/bin/bash

site="hello"
wDir="/home/websites/${site}/httpdocs/"

for file in $(find "${wDir}" -name "*.css")
do
   echo "$file";
done
exit 0;

即使我定义了起始目录,shellcheck 也会警告我,但脚本工作得很好。

root@me /scripts/ # shellcheck test.sh

In test.sh line 6:
for file in $(find "${wDir}" -name "*.css")
            ^-- SC2044: For loops over find output are fragile. Use find -exec or a while read loop.

答案1

问题正是 shellcheck 告诉您的:迭代或类似命令for的输出的循环是脆弱的。find例如:

$ ls
'a file with spaces' 

$ for file in $(find . ); do    echo "$file"; done
.
./a
file
with
spaces

安全的方法是使用-execof find

$ find . -exec echo  {} \;
.
./a file with spaces

或者使用while循环:

$ find . -print0 | while IFS= read -r -d '' file; do echo "$file"; done
.
./a file with spaces

答案2

使用for循环输出find充其量是一种反模式。看BashFAQ/001 - 如何逐行(和/或逐字段)读取文件(数据流、变量)?因为原因。将while如下所示的循环与命令一起使用read。下面的命令find使用 NULL 字节来分隔输出,并且read命令通过分割该字节来读取,以便安全地处理名称中包含特殊字符的所有文件(包括换行符)

#!/usr/bin/env bash

site="hello"
wDir="/home/websites/${site}/httpdocs/"

find "${wDir}" -name "*.css" -type f -print0 | while IFS= read -r -d '' file; do
    printf '%s\n' "$file"
done

或者完全避免使用管道并进行流程替代

while IFS= read -r -d '' file; do
    printf '%s\n' "$file"
done< <(find "${wDir}" -name "*.css" -type f -print0)

网络外壳检查没有报告上述两个片段中的任何一个的任何问题。

相关内容