Eu tenho o comando find que exibe arquivos no meu projeto:
find . -type f -not -path './node_modules*' -a -not -path '*.git*' \
-a -not -path './coverage*' -a -not -path './bower_components*' \
-a -not -name '*~'
Como posso filtrar os arquivos para não mostrar os que estão em .gitignore?
Eu pensei em usar:
while read file; do
grep $file .gitignore > /dev/null && echo $file;
done
mas o arquivo .gitignore pode ter padrões glob (também não funcionará com caminhos se o arquivo estiver em .gitignore). Como posso filtrar arquivos com base em padrões que podem ter globs?
Responder1
git
fornecegit-check-ignore
para verificar se um arquivo foi excluído por .gitignore
.
Então você poderia usar:
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 {} +
Observe que você pagaria um grande custo por isso porque a verificação foi realizada para cada arquivo.
Responder2
Para mostrar os arquivos que estão no seu checkout e que são rastreados pelo Git, use
$ git ls-files
Este comando tem diversas opções para mostrar, por exemplo, arquivos em cache, arquivos não rastreados, arquivos modificados, arquivos ignorados, etc. Consulte git ls-files --help
.
Responder3
existe um comando git para fazer exatamente isso: por exemplo
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
Como você afirmou, ele fará um grep básico com a maioria das opções normais do grep, mas não pesquisará .git
nenhum dos arquivos ou pastas do seu .gitignore
arquivo.
Para mais detalhes, consulteman git-grep
Submódulos:
Se você tiver outros repositórios git dentro deste repositório git (eles devem estar em submódulos), você --recurse-submodules
também pode usar o sinalizador para pesquisar nos submódulos
Responder4
Você pode usar um array no qual o bash glob será executado.
Tendo arquivos como este:
touch file1 file2 file3 some more file here
E ter um ignore
arquivo como este
cat <<EOF >ignore
file*
here
EOF
Usando
arr=($(cat ignore));declare -p arr
Resultará nisso:
declare -a arr='([0]="file" [1]="file1" [2]="file2" [3]="file3" [4]="here")'
Você pode então usar qualquer técnica para manipular esses dados.
Eu pessoalmente prefiro algo assim:
awk 'NR==FNR{a[$1];next}(!($1 in a))' <(printf '%s\n' "${arr[@]}") <(find . -type f -printf %f\\n)
#Output
some
more
ignore