Znajdź pliki, których nie ma w .gitignore

12

Mam polecenie, które wyświetla pliki w moim projekcie:

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

Jak mogę filtrować pliki, aby nie wyświetlały się w .gitignore?

Myślałem, że używam:

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

ale plik .gitignore może mieć wzorce globów (również nie będzie działać ze ścieżkami, jeśli plik znajduje się w .gitignore), jak mogę filtrować pliki na podstawie wzorców, które mogą mieć globusy?

jcubic
źródło

Odpowiedzi:

11

gitzapewnia git-check-ignoresprawdzenie, czy plik jest wykluczony przez .gitignore.

Więc możesz użyć:

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

Pamiętaj, że zapłaciłbyś za to duże koszty, ponieważ sprawdzanie zostało wykonane dla każdego pliku.

Cuonglm
źródło
Co jest find-sh {} +na końcu
jcubic 11.04.17
@jcubic patrz unix.stackexchange.com/q/12902/38906
cuonglm
Ok a co find-sh?
jcubic 11.04.17
@jcubic to nazwa, którą nadałeś skryptowi inline-sh, więc w przypadku wystąpienia błędu otrzymasz znaczący komunikat o błędzie
cuonglm
@jcubic Spróbuj find /tmp -exec sh -c ': "${non_existed_var:?foo}"' find-sh {} +na przykład
cuonglm
9

istnieje komenda git do wykonania dokładnie tego: np

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

Jak już wspomniałeś, wykona podstawowy grep i większość normalnych opcji grep, ale nie przeszuka .gitani żadnego z plików lub folderów w twoim .gitignorepliku.
Aby uzyskać więcej informacji, zobaczman git-grep

Podmoduły:

Jeśli masz inne repozytorium git wewnątrz tego repozytorium git (powinny znajdować się w submodułach), możesz użyć flagi, --recurse-submodulesaby przeszukać również submoduły

the_velour_fog
źródło
Świetnie, prawie działa, ponieważ mam inne repozytorium git w bieżącym katalogu, dlatego mam „* .git”.
jcubic 11.04.17
8

Aby wyświetlić pliki, które znajdują się w kasie i które są śledzone przez Git, użyj

$ git ls-files

To polecenie ma wiele opcji wyświetlania, np. Pliki w pamięci podręcznej, pliki bez śledzenia, pliki zmodyfikowane, pliki ignorowane itp git ls-files --help. Zobacz .

Kusalananda
źródło
Zastanawiam się również, git ls-filesale nie sądzę, że ma opcję pokazania nieśledzonych plików, który?
cuonglm
1
@cuonglm -o(inny). Np.git ls-files -o -X .gitignore
Kusalananda
Ach tak, ale nie może obsłużyć przypadku, w którym plik był wcześniej śledzony, ale zawierał .gitignore.
cuonglm
Drobna uwaga: nie wyświetla rzeczywistych plików z systemu, ale pliki zawarte w historii git. Może to być subtelna różnica w systemach bez rozróżniania wielkości liter (np. Udziały Windows). Powiedzmy, że popełniłem ./foo.txt, ale potem zmień nazwę na ./Foo.txt. Niektórzy klienci git nie rozpoznają tej zmiany i git ls-fileswypisują ./foo.txt, gdy findwypisują ./Foo.txt
Griddo
2

Możesz użyć tablicy, w której zostanie wykonany glob bash.

Posiadanie takich plików:

touch file1 file2 file3 some more file here

I posiadanie takiego ignorepliku

cat <<EOF >ignore
file*
here
EOF

Za pomocą

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

Spowoduje to:

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

Następnie możesz użyć dowolnej techniki do manipulowania tymi danymi.

Osobiście wolę coś takiego:

awk 'NR==FNR{a[$1];next}(!($1 in a))'  <(printf '%s\n' "${arr[@]}") <(find . -type f -printf %f\\n)
#Output
some
more
ignore
George Vasiliou
źródło
gitignorejest nadzbiorem bashglobu, będziesz tęsknił za czymś takim!file*
cuonglm
@cuonglm Co masz na myśli !file*? Jako wzorzec globu w pliku zignorować czy jako nazwa pliku?
George Vasiliou,
gitignoreakceptuj wzorzec pliku, tak !file*aby wykluczyć pliki, zaczynając od file, a także podwójną gwiazdkę**
cuonglm
.gitignorema wiele funkcji, z których wszystkie mogą nie być tak łatwe do wdrożenia bezpośrednio w Bash: git-scm.com/docs/gitignore . Chociaż ignorowanie składające się z prostych globusów powinno być wykonalne w zwykłym
Bashu
@cuonglm Masz na myśli tłumaczenie !jako nie? Być może rozszerzone globowanie poradzi sobie z tą sytuacją. O Doublestar bash sobie z tym poradzi shopt -s globstar.
George Vasiliou,