我将查找结果保存在变量中,并且通过在输出周围添加单引号来保护文件名中的空格。所以 for 循环可以完美地工作。
我的问题是,当我打算 grep 其中一个文件时,它显示“文件不存在”,因为实际上是将单引号作为文件名的一部分。
我怎样才能克服这个?
all_files=$(find . -type f -printf "'%p'")
for file in $all_files
do
grep 'hello' $file ### this says "file.not found because of the single quotes
done
答案1
您没有通过在 .txt 的输出中添加引号来保护文件名的值find
。循环仍然会被视为'a filename'
需要迭代的两件事。正如您所注意到的,引号也将是字符串的一部分。
相反,运行你grep
的find
:
find . -type f -exec grep 'hello' {} \;
这将为grep
找到的每个文件执行一次。
find . -type f -exec grep 'hello' {} +
这将grep
一次执行尽可能多的文件(因此也输出具有多个文件的批次的文件名,使用-h
GNUgrep
或兼容的选项不打印文件名)。
仍然使用 GNU grep
:
grep -D skip -r 'hello' .
这将grep
在当前目录上递归运行,跳过非常规文件(就像-type f
for 一样find
),但仍然会查找常规文件的符号链接(就像使用 GNU 一样find -xtype f
)。
答案2
如果您想存储文件列表以供以后循环使用,最好将其存储在数组中。
和bash
:
readarray -td '' all_files < <(find . -type f -print0)
for file in "${all_files[@]}"; do
grep hello "$file"
done
与zsh
(同样的事情,但得到一个排序列表作为奖励):
all_files=(./**/*(ND.))
for file ($all_files) grep hello $file
答案3
打印所有具有“hello”模式的文件名,
find . -type f -print0 | xargs -0 -L1 grep -l 'hello'
或与内find
联grep
find . -type f -exec grep -l 'hello' {} \;
或者更简单(如果您只有常规文件)
grep -Rl 'hello' .
答案4
对于任何对我如何解决这个问题感兴趣的人,我最终得到:
all_files=$( find . -type f -name *.txt -printf '%p' )
while read file
do
grep 'hello' "$filename"
.....
done <<< "$all_files"
我知道这是一个不好的做法。但对于我的特定用例,我需要对每个文件名执行很多操作。不只是摸索。现在它完美地工作了。
谢谢!