Используйте find, чтобы получить все папки, у которых нет подпапки.git
Как использовать find, чтобы получить все папки, которые не имеют папки.git?
На этой структуре::
$ tree -a -d -L 2
.
├── a
│ └── .git
├── b
│ ├── b1
│ └── b2
├── c
└── d
└── .git
├── lkdj
└── qsdqdf
Это::
$ find . -name ".git" -prune -o -type d -print
.
./a
./b
./b/b1
./b/b2
./c
./d
$
получить все папки, кроме.git
Я хотел бы получить это::
$ find . ...
.
./b
./b/b1
./b/b2
./c
$
3 ответа
Это неэффективно (запускает кучу подпроцессов), но следующее будет работать с GNU или современным BSD find
:
find . -type d -exec test -d '{}/.git' ';' -prune -o -type d -print
Если вам не гарантировано иметь find
с любой функциональностью, не гарантированной в стандарте POSIX, вам может потребоваться еще больше потери эффективности (чтобы сделать {}
свой собственный токен, а не подстрока, с помощью оболочки, запускающей тест):
find . -type d -exec sh -c 'test -d "$1/.git"' _ '{}' ';' -prune -o -type d -print
Это работает с помощью -exec
в качестве предиката, запускающего тест, который find
не имеет встроенной поддержки.
Обратите внимание на использование неэффективных -exec [...] {} [...] \;
а не более эффективный -exec [...] {} +
; так как последний передает несколько имен файлов каждому вызову, он не имеет возможности вернуть отдельные результаты для каждого имени файла и поэтому всегда оценивается как истина.
Если вы не возражаете против использования временного файла, то:
find . -type d -print > all_dirs
fgrep -vxf <(grep '/\.git$' all_dirs | sed 's#/\.git$##') all_dirs | grep -vE '/\.git$|/\.git/'
rm all_dirs
- Первый шаг - получить все пути подкаталогов в файл all_dirs.
- Вторые шаги отфильтровывают каталоги, которые имеют подкаталог.git, а также подкаталоги.git.
-x
опция необходима, потому что нам нужно исключить только те строки, которые полностью совпадают.
Это будет немного более эффективным по сравнению с ответом Чарльза в том, что он не запускает так много подпроцессов. Тем не менее, это даст неверный вывод, если в любом из каталогов будет символ перевода строки.
Если вы хотите найти только верхние каталоги, добавьте опцию-maxdepth 1
нравиться
$ find . -type d -exec test -d '{}/.git' ';' -maxdepth 1 -prune -o -type d -print
.
./b
./c
$