ค้นหาไฟล์ที่ไม่อยู่ใน. gitignore


12

ฉันมีคำสั่ง find ที่แสดงไฟล์ในโครงการของฉัน:

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) ฉันจะกรองไฟล์ตามรูปแบบที่อาจมี globs ได้อย่างไร

คำตอบ:


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 เป็นชื่อที่คุณให้กับสคริปต์แบบอินไลน์ดังนั้นในกรณีที่เกิดข้อผิดพลาดคุณจะได้รับข้อความแสดงข้อผิดพลาดที่มีความหมาย
cuonglm

@jcubic ลองfind /tmp -exec sh -c ': "${non_existed_var:?foo}"' find-sh {} +ตัวอย่าง
cuonglm

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

submodules:

หากคุณมี repos git อื่น ๆ ภายใน repo git นี้ (พวกเขาควรจะอยู่ใน submodules) จากนั้นคุณสามารถใช้ธง--recurse-submodulesเพื่อค้นหาใน submodules เช่นกัน


เยี่ยมมากมันใช้งานได้เพราะฉันมี repos git อื่น ๆ ในไดเรกทอรีปัจจุบันนั่นเป็นเหตุผลที่ฉันมี "* .git"
jcubic

8

ในการแสดงไฟล์ที่อยู่ในการชำระเงินของคุณและถูกติดตามโดย Git ให้ใช้

$ git ls-files

คำสั่งนี้มีจำนวนของตัวเลือกสำหรับการแสดงเช่นแคชไฟล์ไฟล์ที่ไม่ได้ติดตาม, แก้ไขไฟล์, ไฟล์ละเว้น ฯลฯ git ls-files --helpดู


ฉันคิดด้วยgit ls-filesแต่ไม่คิดว่ามันมีตัวเลือกในการแสดงไฟล์ที่ไม่ได้ติดตามซึ่งเป็นไฟล์ใด
cuonglm

1
@cuonglm -o(อื่น ๆ ) เช่นgit ls-files -o -X .gitignore
Kusalananda

ใช่ แต่ไม่สามารถจัดการกับกรณีที่มีการติดตามไฟล์ก่อนหน้า แต่รวมอยู่.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

gitignoreเป็น superset of bashglob คุณจะพลาดบางอย่างเช่น!file*
cuonglm

@cuonglm คุณหมายถึง!file*อะไร? เป็นรูปแบบ glob ในไฟล์ที่ไม่สนใจหรือเป็นชื่อไฟล์หรือไม่?
George Vasiliou

gitignoreยอมรับรูปแบบไฟล์ที่ต้องการ!file*ยกเว้นไฟล์ที่ขึ้นต้นด้วยfileและยังเป็นดาวคู่**
cuonglm

.gitignoreมีพวงของคุณสมบัติทั้งหมดที่อาจจะไม่เป็นที่ง่ายต่อการใช้โดยตรงในทุบตี: git-scm.com/docs/gitignore แม้ว่าการละเว้นที่ประกอบด้วย globs แบบง่าย ๆ ควรทำได้ใน Bash ธรรมดาโดยไม่ต้อง awk หรืออย่างนั้น
ilkkachu

@cuonglm คุณหมายถึงการแปลของ!not not? บางทีการขยายไปรอบ ๆ สามารถจัดการกับสถานการณ์นี้ได้ เกี่ยวกับ doublestar shopt -s globstarทุบตีสามารถจัดการกับมันด้วย
George Vasiliou
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.