Grep 多个文件,其文件名存储在一个变量中

Mik*_*z45 0 bash shell grep

考虑变量files

$ echo $files
1.txt 2.txt 3.txt
Run Code Online (Sandbox Code Playgroud)

有没有办法告诉 grep 它必须为单个字符串 grep 出现在变量中的每个文件?我试过了:

$ grep "string" "$files"
Run Code Online (Sandbox Code Playgroud)

但我得到一个1.txt 2.txt 3.txt No such file of directory错误。我已经有一段时间没有使用 shell 工作了,所以我不记得如何进行这项工作。

Dav*_*ica 9

使用存储在的文件名列表files,例如

files="1.txt 2.txt 3.txt"
Run Code Online (Sandbox Code Playgroud)

当你引用"$files"(做好引用您的变量),并尝试使用"$files"grep命令字分割上的内容$files不会发生?为什么?引用可防止分词,因此会grep尝试查找命名的文件"1.txt 2.txt 3.txt",该文件当然不会退出并生成错误。

您可以通过简单地使用un-quoted来使用grepwith - 但这不是要走的路。为什么?在存储用于命令的文件名时,您必须确保存储的文件集合可以处理所有有效的文件名。这包括带空格的文件名。如果您尝试将未引用的方法用于:$files$files

files="file 1.txt file 2.txt file 3.txt"
Run Code Online (Sandbox Code Playgroud)

使用grep(或任何命令)不带引号$files将无法查找 6 个文件、file1.txtfile2.txtfile , 3.txt

这个问题在BashFAQ #50 中详细描述和讨论 ,特别是5. 我正在构建一个基于仅在运行时已知的信息的命令。解决方案是将您的文件名存储在一个数组中(如果您需要存储它们)。正如@Jetchisel 指出的,这可以通过创建files一个数组来简单地处理:

files=(*.txt)
Run Code Online (Sandbox Code Playgroud)

(或files=([1-3].txt)将选择限制为1.txt2.txt3.txt

通过使用数组,您可以使用带引号的形式,"${files[@]}"该形式将为单独引用的命令提供每个文件名,例如

grep "string" "${files[@]}"
Run Code Online (Sandbox Code Playgroud)

将扩展到:

grep "string" "1.txt" "2.txt" "3.txt"
Run Code Online (Sandbox Code Playgroud)

这样,无论文件名是什么,也不管它是否包含空格,grep都会看到正确的文件名。例如:

files=("file 1.txt" "file 2.txt" "file 3.txt")
Run Code Online (Sandbox Code Playgroud)

使用数组的引用形式 withgrep将导致:

grep "strings" "file 1.txt" "file 2.txt" "file 3.txt"
Run Code Online (Sandbox Code Playgroud)

因此,您的原始问题是由抑制word-splitting引起的,但是您尝试使用文件名列表本身就存在很大问题。如果您需要在变量中捕获文件名列表,则出于上述原因使用数组。如果您可以避免完全存储它们而只需使用grep命令与 glob 一起*.txt,那么您就可以避免这两个问题。

如果您还有其他问题,请告诉我。