У меня есть команда 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). Как мне отфильтровать файлы на основе шаблонов, которые могут иметь шаблоны glob?
решение1
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 {} +
Обратите внимание, что за это вам пришлось бы заплатить большую цену, поскольку проверка выполнялась для каждого файла.
решение2
Чтобы отобразить файлы, которые находятся в вашем извлечении и отслеживаются Git, используйте
$ git ls-files
Эта команда имеет ряд параметров для отображения, например, кэшированных файлов, неотслеживаемых файлов, измененных файлов, игнорируемых файлов и т. д. См. git ls-files --help
.
решение3
есть команда 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
Подмодули:
Если у вас есть другие репозитории git внутри этого репозитория git (они должны быть в подмодулях), то вы можете использовать этот флаг --recurse-submodules
для поиска также и в подмодулях.
решение4
Вы можете использовать массив, в котором будет выполняться 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