欢迎各位兄弟 发布技术文章
这里的技术是共享的
while IFS= read -r -d '' file; do
if [[ "$file" != /Library/* && "$file" != /System/Library/* ]]; then
files+=("$file")
fi
done < <(mdfind '((kMDItemFSName == "*AAAA*"cd) || (kMDItemFSName == "*BBBB*"cd) || (kMDItemFSName == "*CCCC*"cd) || (kMDItemFSName == "*DDDD*"cd) || (kMDItemFSName == "*EEEE*"cd)) && ((kMDItemFSName == "*.pdf"cd) || (kMDItemFSName == "*.ppt"cd) || (kMDItemFSName == "*.pptx"cd) || (kMDItemFSName == "*.key"cd) || (kMDItemFSName == "*.png"cd) || (kMDItemFSName == "*.jpg"cd) || (kMDItemFSName == "*.jpeg"cd))' -0)
与 while IFS= read -r -d '' file; do
if [[ "$file" != /Library/* && "$file" != /System/Library/* ]]; then
files+=("$file")
fi
done <<(mdfind '((kMDItemFSName == "*AAAA*"cd) || (kMDItemFSName == "*BBBB*"cd) || (kMDItemFSName == "*CCCC*"cd) || (kMDItemFSName == "*DDDD*"cd) || (kMDItemFSName == "*EEEE*"cd)) && ((kMDItemFSName == "*.pdf"cd) || (kMDItemFSName == "*.ppt"cd) || (kMDItemFSName == "*.pptx"cd) || (kMDItemFSName == "*.key"cd) || (kMDItemFSName == "*.png"cd) || (kMDItemFSName == "*.jpg"cd) || (kMDItemFSName == "*.jpeg"cd))' -0)
区别
这两个代码片段的区别在于 done
行末的 进程替换(Process Substitution) 语法写法不同:
bashdone < <(mdfind ... -0)
<(mdfind ... -0)
是一个 进程替换,它会将 mdfind
命令的输出作为一个临时文件描述符传递给 while
循环。
前面的 <
是标准输入重定向,表示从 <(mdfind ...)
的结果读取数据。
为什么正确?
<(command)
生成一个类似 /dev/fd/63
的文件描述符,供 while
循环逐行读取。
-0
选项让 mdfind
输出以 \0
(NULL 字符)分隔,而 IFS= read -r -d ''
能够正确解析这种格式,避免文件名含空格或换行符时的解析错误。
bashdone <<(mdfind ... -0)
这里 <<(
缺少空格,使得 shell 解析错误。
可能被解释为:
<<
被当作 here-document(嵌入式文档) 的开始,但后面没有匹配的结束标记(如 EOF
)。
或者,<<(
被当作一个无效的语法,直接报错(bash 会提示语法错误)。
正确形式:< <(command)
→ 先进程替换 <(...)
,再输入重定向 <
,中间必须加空格。
错误形式:<<(...)
→ shell 无法识别,要么解析成 here-document(失败),要么直接报错。
这段代码的目的是:
用 mdfind
搜索 文件名包含 AAAA
、BBBB
、CCCC
、DDDD
或 EEEE
,且扩展名是 .pdf
/.ppt
/.pptx
/.key
/.png
/.jpg
/.jpeg
的文件。
排除系统目录:跳过 /Library/
和 /System/Library/
下的文件。
安全处理文件名:-0
和 IFS= read -r -d ''
确保即使文件名含空格或换行符也能正确读取。
如果你的代码写成 <<(...)
,bash 会报错,改为 < <(...)
即可正常运行。