Получение содержимого каталога, исключающего все, что находится внутри .git в bash

#bash #git #git-bash

#удар #мерзавец #гит-баш

Вопрос:

Мне нужно получить номер содержимого каталога, который является репозиторием git.

Мне нужно узнать номер:

 1) Other directories inside the directory I am currently iterating (and the other sub-directories inside them if they exist)  2) .txt files inside the directory and its sub-directories  3) All the non-txt files inside the directory and its sub-directories  

Во всех вышеперечисленных случаях я должен игнорировать каталог .git, а также все файлы и каталоги, которые находятся внутри него.

Кроме того, я должен использовать исключительно скрипт bash. Я не могу использовать другой язык программирования.

Прямо сейчас я использую следующие команды для достижения этой цели:

  1. Чтобы получить все .txt файлы, которые я использую : find . -type f ( -name "*.txt" ) . Внутри нет .txt файлов .git , так что это работает.
  2. Чтобы получить все non-txt файлы, которые я использую: find . -type f ( ! -name "*.txt" ) . Проблема в том, что я также получаю все файлы .git и не знаю, как их игнорировать.
  3. Чтобы получить все directories и sub-directories Я использую: find . -type d . Я не знаю, как игнорировать .git каталог и его подкаталоги

Ответ №1:

Самый простой способ — просто добавить эти дополнительные тесты:

 find . ! -path './.git/*' ! -path ./.git -type f -name '*.txt'  

Проблема в том, что это ./.git все еще обходится без необходимости, что требует времени.

Вместо -prune этого можно использовать. -prune это не тест (например -path , или -type ). Это действие. Действие «не спускайтесь по текущему пути, если это каталог». Он должен использоваться отдельно для действия печати.

 # task 1 find . -path './.git' -prune -o -type f -name '*.txt' -print  # task 2 find . -path './.git' -prune -o -type f ! -name '*.txt' -print  # task 3 find . -path './.git' -prune -o -type d -print  
  • Если -print не указано, ./.git также печатается как действие по умолчанию.
  • Я использовал -path ./.git , потому что вы сказали « .git каталог». Если по какой-то причине в дереве есть другие .git каталоги, они будут пройдены и распечатаны. Чтобы игнорировать все каталоги в названном дереве .git , замените -path ./.git на -name .git .

Комментарии:

1. Большое вам спасибо. Это работает идеально. Я просто хочу задать один вопрос. Когда я использую find . -path './.git' -prune -o -type d -print , я получаю . каталог. Представляет ли это текущий каталог? Кроме того, как я могу игнорировать это в выводе?

2. @SimosNeopoulos Да, я чуть было не упомянул об этом. Это текущий каталог, указанный с find . помощью . Этот префикс будет включен, если он совпадает. Это не совпадает в первых двух из-за -type f . Вы можете сделать: find . -mindepth 1 -path './.git' -prune -o -type d -print или find . -path './.git' -prune -o -type d ! -path . -print .

3. Лично я бы использовал -name .git -prune , так как Git не будет хранить ничего с именем .git (по соображениям безопасности), и, следовательно, более простой -name тест также соответствует тому, что делает Git. Но, конечно, и то, и другое работает.

Ответ №2:

Иногда написание цикла bash более понятно, чем однострочное

 for f in $(find .); do  if [[ -d $f amp;amp; "$f" == "./.git" ]]; then  echo "skipping dir $f";  else  echo "do something with $f";  fi; done  

Комментарии:

1. Это не работает. Я запустил код, но все равно получаю все файлы и папки .git

2. вы должны изменить мой пример, чтобы он соответствовал вашим потребностям — там есть все необходимые компоненты …