Tìm tệp không có trong .gitignore


11

Tôi đã tìm thấy lệnh hiển thị các tập tin trong dự án của tôi:

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

Làm cách nào tôi có thể lọc các tệp để nó không hiển thị các tệp trong .gitignore?

Tôi nghĩ rằng tôi sử dụng:

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

nhưng tệp .gitignore có thể có các mẫu hình cầu (cũng sẽ không hoạt động với các đường dẫn nếu tệp nằm trong .gitignore), Làm cách nào tôi có thể lọc các tệp dựa trên các mẫu có thể có các khối?

Câu trả lời:


11

gitcung cấp git-check-ignoređể kiểm tra xem một tập tin được loại trừ bởi .gitignore.

Vì vậy, bạn có thể sử dụng:

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 {} +

Lưu ý rằng bạn sẽ trả chi phí lớn cho việc này vì kiểm tra đã được thực hiện cho mỗi tệp.


Là những gì find-sh {} +cuối cùng?
jcubic


Ok, và những gì find-sh?
jcubic

@jcubic đó là tên bạn đã đặt cho tập lệnh inline-sh, vì vậy trong trường hợp xảy ra lỗi, bạn sẽ có một thông báo lỗi có ý nghĩa
cuonglm

@jcubic Hãy thử find /tmp -exec sh -c ': "${non_existed_var:?foo}"' find-sh {} +ví dụ
cuonglm

9

có một lệnh git để làm chính xác điều này: vd

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

Như bạn đã nói, nó sẽ thực hiện một grep cơ bản trong hầu hết các tùy chọn grep thông thường, nhưng nó sẽ không tìm kiếm .githoặc bất kỳ tệp hoặc thư mục nào trong .gitignoretệp của bạn .
Để biết thêm chi tiết, xemman git-grep

Các mô hình con:

Nếu bạn có repo git khác bên trong repo git này, (chúng nên ở dạng con), bạn cũng có thể sử dụng cờ --recurse-submodulesđể tìm kiếm trong các mô hình con


Tuyệt vời, nó gần như hoạt động vì tôi có các repo git khác trong thư mục hiện tại, đó là lý do tại sao tôi có "* .git".
jcubic

8

Để hiển thị các tệp trong thanh toán của bạn và được theo dõi bởi Git, hãy sử dụng

$ git ls-files

Lệnh này có một số tùy chọn để hiển thị, ví dụ: các tệp được lưu trong bộ nhớ cache, các tệp không bị theo dõi, các tệp đã sửa đổi, các tệp bị bỏ qua, v.v. Xem git ls-files --help.


Tôi cũng nghĩ về git ls-filesnhưng không nghĩ rằng nó có tùy chọn để hiển thị các tệp không bị theo dõi, cái nào?
cuonglm

1
@cuonglm -o(khác). Ví dụ:git ls-files -o -X .gitignore
Kusalananda

À đúng, nhưng không thể xử lý trường hợp tệp được theo dõi trước mà bao gồm trong .gitignore.
cuonglm

Lưu ý nhỏ: điều này không liệt kê các tệp thực tế từ hệ thống mà là các tệp có trong lịch sử git. Đây có thể là một sự khác biệt tinh tế trên các hệ thống không phân biệt chữ hoa chữ thường (ví dụ: cổ phiếu Windows). Nói, tôi đã cam kết ./foo.txt nhưng sau đó đổi tên thành ./Foo.txt. Một số khách hàng git sẽ không nhận ra thay đổi này và git ls-filesxuất ra ./foo.txt trong khi findsẽ xuất ./Foo.txt
Griddo

2

Bạn có thể sử dụng một mảng trong đó bash global sẽ được thực hiện.

Có tệp như thế này:

touch file1 file2 file3 some more file here

Và có một ignoretập tin như thế này

cat <<EOF >ignore
file*
here
EOF

Sử dụng

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

Sẽ dẫn đến điều này:

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

Sau đó, bạn có thể sử dụng bất kỳ kỹ thuật nào để thao tác với những dữ liệu đó.

Cá nhân tôi thích một cái gì đó như thế này:

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

gitignorelà siêu sao của toàn bashcầu, bạn sẽ bỏ lỡ một cái gì đó như!file*
cuonglm

@cuonglm Ý bạn là !file*gì? Là một mô hình toàn cầu trong tập tin bỏ qua hoặc như một tên tệp?
George Vasiliou

gitignorechấp nhận mẫu tệp muốn !file*loại trừ các tệp bắt đầu bằng filevà sao đôi**
cuonglm

.gitignorecó một loạt các tính năng, tất cả chúng có thể không dễ thực hiện trực tiếp trong Bash: git-scm.com/docs/gitignore . Mặc dù bỏ qua bao gồm chỉ những khối u đơn giản nên có thể thực hiện được ở Bash đơn giản, mà không cần awk hay đại loại thế
ilkkachu

@cuonglm Ý bạn là dịch !như không? Có lẽ hả hê kéo dài có thể xử lý tình huống này. Về doublestar, bash có thể xử lý nó với shopt -s globstar.
George Vasiliou
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.