Знайдіть файли, які не містяться у .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 може мати шаблони глобуса (також він не працюватиме з шляхами, якщо файл знаходиться у .gitignore). Як я можу фільтрувати файли на основі шаблонів, у яких можуть бути глобуси?

Відповіді:


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, але він не буде шукати .gitжоден з файлів чи папок у вашому .gitignoreфайлі.
Детальніше дивman git-grep

Підмодулі:

Якщо у вас є інші git repos всередині цього git repo (вони повинні бути в підмодулях), ви можете використовувати прапор --recurse-submodulesдля пошуку в підмодулях


Чудово, це майже працює, тому що у мене є інші git repos всередині поточного каталогу, тому у мене є "* .git".
jcubic

8

Щоб показати файли, які знаходяться у вашій касі і відслідковуються Git, використовуйте

$ git ls-files

Ця команда має ряд варіантів відображення, наприклад, кешовані файли, непотрібні файли, модифіковані файли, ігноровані файли тощо. Див git ls-files --help.


Я також замислююся над цим, git ls-filesале не думаю, що він має можливість відображати незатребувані файли, який із них?
cuonglm

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

gitignoreсуперсеть bashглобуса, ви пропустите щось на зразок!file*
cuonglm

@cuonglm Що ти маєш на увазі під собою !file*? Як глобальний зразок у файлі ігнорування чи як ім'я файлу?
Джордж Васильоу

gitignoreприйняти шаблон файлу, як !file*виключати файли, починаючи з file, а також подвійну зірку**
cuonglm

.gitignoreмає безліч функцій, які можуть бути не такими простими в реалізації безпосередньо на Bash: git-scm.com/docs/gitignore . Хоча ігнори, що складаються з просто простих глобусів, повинні бути
виконані на простому баші

@cuonglm Ви маєте на увазі переклад !як ні? Можливо, розширена глобалізація впорається з цією ситуацією. Щодо Doublestar, bash може впоратися з цим shopt -s globstar.
Джордж Васильоу
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.