让我举个例子吧:
$ echo Hello > file1
$ echo Hello > file2
$ echo Hello > .file3
$ grep Hello * 2>/dev/null
file1:Hello
file2:Hello
在这里你可以看到 grep 被忽略,.file3
它是从.
预期结果:
$ grep Hello * 2>/dev/null
.file3:Hello
file1:Hello
file2:Hello
在 的情况下ls
,有一个参数-a
告诉不要忽略以 开头的条目,.
但我找不到任何功能grep
那么,有没有办法告诉grep
不要忽略以 开头的条目.
?或者为什么grep
忽略它们?
答案1
*
与文件名扩展中的前导句点不匹配.
。该规则由 POSIX 指定。
通过模式匹配,它可以工作:
$ sh -c 'case . in *) echo 1;; esac'
1
POSIXly:
find . ! -name . -prune -type f -exec grep 'pattern' /dev/null {} +
这种方法比使用 shell 通配符具有优势。你永远不会得到参数列表太长文件太多时出错。
答案2
正如其他人所说,*
默认情况下,glob 不会包含隐藏文件(名称以点开头的文件)。解决这个问题的一个简单方法是使用两个 glob:
grep Hello * .*
不利的一面是,除了基于 Forsyth shell 的zsh
,或 shell(现在还有,或 OpenBSD 之类的衍生产品),这会导致在搜索目录和时抱怨:fish
pdksh
mksh
posh
sh
grep
.
..
$ grep Hello * .*
file1:Hello
file2:Hello
grep: .: Is a directory
grep: ..: Is a directory
.file3:Hello
您可以忽略这些错误(它们在这种情况下并不重要),也可以使用一个简单的循环并检查目标是否是常规文件(在符号链接解析之后):
$ for file in .* *; do [ -f "$file" ] && grep -H -- Hello "$file"; done
.file3:Hello
file1:Hello
file2:Hello
答案3
对于包含除.
和 之外的隐藏文件的 glob ..
:
zsh
:grep Hello ./*(D)
(您还需要
./
以 开头的文件名-
)。或者:(set -o dotglob; grep Hello ./*)
glob的另一个优点
zsh
是您可以指定只需要常规文件(使用.
glob 限定符):grep Hello ./*(D.)
ksh93
:(FIGNORE='.?(.)'; grep Hello ./*)
bash
:(shopt -s dotglob; grep Hello ./*)
tcsh
:(set globdot; grep Hello ./*)
fish
:grep Hello {.,}*
Forsyth shell 及其衍生产品(
pdksh
、OpenBSDsh
、、posh
...mksh
)以及fish
:grep Hello ./.* ./*
rc
,es
:grep Hello ./.[~.]* ./..?* ./*
Bourne shell、ksh88 和 Almquist shell 衍生物:
grep Hello ./.[!.]* ./..?* ./*
csh
:grep Hello ./.[^.]* ./..?* ./*
使用zsh
、(t)csh
和fish
,如果 glob 与任何文件都不匹配,则不会运行该命令。在其他 shell 中,不匹配的 glob 将按原样传递给grep
,并grep
会抱怨相应的文件不存在。
答案4
其他人正确地说,*
不会匹配以点开头的文件。许多答案中给出了各种解决方案,其中大多数都有一些漏洞或其他(例如包括 . & .. ;或排除以多个 Dots 开头的文件;或包括 Sub-Directories ;或涉及很长的命令-行)所有这些都为这个问题提供了一些新的观点。
我的简单解决方案(对于 bash 用户)是使用shopt -s dotglob
它通知 bash 在 * glob 中包含点文件。
对于 POSIX 兼容性或其他 shell 的使用,我希望其他答案有用。
shopt -s dotglob
解决方案亮点: 不会包括。和 .. ;它不会以递归方式包含子目录;它很短;它可以放在 .bashrc 文件中。