查找不在.gitignore中的文件


12

我有找到在我的项目中显示文件的命令:

find . -type f -not -path './node_modules*' -a -not -path '*.git*' \
       -a -not -path './coverage*' -a -not -path './bower_components*' \
       -a -not -name '*~'

如何过滤文件,使其不显示.gitignore文件中的文件?

我以为我使用:

while read file; do
    grep $file .gitignore > /dev/null && echo $file;
done

但是.gitignore文件可以具有glob模式(如果文件位于.gitignore中,它也将不适用于路径),如何根据可能具有glob的模式过滤文件?

Answers:


11

git提供git-check-ignore检查文件是否被排除的功能.gitignore

因此,您可以使用:

find . -type f -not -path './node_modules*' \
       -a -not -path '*.git*'               \
       -a -not -path './coverage*'          \
       -a -not -path './bower_components*'  \
       -a -not -name '*~'                   \
       -exec sh -c '
         for f do
           git check-ignore -q "$f" ||
           printf '%s\n' "$f"
         done
       ' find-sh {} +

请注意,您将为此付出高昂的代价,因为检查是针对每个文件执行的。


到底是什么find-sh {} +
jcubic


好吧,那是find-sh什么?
jcubic

@jcubic这是您为inline-sh脚本指定的名称,因此,如果发生错误,您将收到有意义的错误消息
cuonglm

@jcubic find /tmp -exec sh -c ': "${non_existed_var:?foo}"' find-sh {} +例如尝试
cuonglm '17

9

有一个git命令可以做到这一点:例如

my_git_repo % git grep --line-number TODO                                                                                         
desktop/includes/controllers/user_applications.sh:126:  # TODO try running this without sudo
desktop/includes/controllers/web_tools.sh:52:   TODO: detail the actual steps here:
desktop/includes/controllers/web_tools.sh:57:   TODO: check if, at this point, the menurc file exists. i.e. it  was created

如您所述,它将执行基本的grep,将执行大多数常规grep选项,但不会搜索.git文件中的任何文件或文件夹.gitignore
有关更多详细信息,请参见man git-grep

子模块:

如果您在此git repo内还有其他git repos(它们应该在子模块中),则也可以使用该标志--recurse-submodules在子模块中进行搜索


太好了,几乎可以使用了,因为我在当前目录中还有其他git repos,这就是为什么我有“ * .git”的原因。
jcubic

8

要显示您的结帐中以及Git跟踪的文件,请使用

$ git ls-files

此命令具有许多显示选项,例如,缓存文件,未跟踪文件,已修改文件,被忽略文件等。请参见git ls-files --help


我也考虑过,git ls-files但不认为它可以显示未跟踪的文件,哪个?
cuonglm '17

1
@cuonglm -o(其他)。例如,git ls-files -o -X .gitignore
库沙兰丹

是的,但是无法处理以前曾跟踪文件但包含在中的情况.gitignore
cuonglm

注意事项:这不会列出系统中的实际文件,而是git历史记录中包含的文件。在不区分大小写的系统(例如Windows共享)上,这可能是微妙的区别。说,我提交了./foo.txt,但是将其重命名为./Foo.txt。某些git客户端将无法识别此更改并git ls-files输出./foo.txt,而find将输出./Foo.txt
Griddo

2

您可以使用将在其中执行bash glob的数组。

具有这样的文件:

touch file1 file2 file3 some more file here

并拥有这样的ignore文件

cat <<EOF >ignore
file*
here
EOF

使用

arr=($(cat ignore));declare -p arr

将导致以下结果:

declare -a arr='([0]="file" [1]="file1" [2]="file2" [3]="file3" [4]="here")'

然后,您可以使用任何技术来处理这些数据。

我个人更喜欢这样的事情:

awk 'NR==FNR{a[$1];next}(!($1 in a))'  <(printf '%s\n' "${arr[@]}") <(find . -type f -printf %f\\n)
#Output
some
more
ignore

gitignorebashglob的超集,您会想念!file*
cuonglm '17

@cuonglm是什么意思!file*?作为忽略文件中的全局模式还是文件名?
乔治·瓦西里乌

gitignore接受文件模式,例如!file*排除以开头的文件file,以及双星**
cuonglm

.gitignore有很多功能,所有这些功能可能都不容易直接在Bash中实现:git-scm.com/docs/gitignore。尽管由简单的glob组成的忽略应该可以在普通的Bash中执行,而没有awk或类似的问题
ilkkachu

@cuonglm你的意思!是不是?也许延长球可以解决这种情况。关于doublestar,bash可以处理shopt -s globstar
乔治·瓦西里乌
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.