6

Я пытаюсь удалить все пустые папки в каталоге. Тем не менее, find . -type f -empty не находит ничего, потому что каждая папка содержит скрытую папку .svn .

Как я могу обойти это?

5 ответов5

3

Незначительные изменения (просто распечатайте каталог и отправьте в xargs позже):

for folder in $(find -type d ! -path *.svn*); do
  if [ "`find $folder ! -path *.svn* ! -path $folder | wc -l`" -eq 0 ]; then
    echo $folder
  fi
done

Поместите это где-нибудь в ваш $PATH , возможно, как svn-empties а затем сначала запустите:

svn-empties

для просмотра списка найденных каталогов (при необходимости измените список) и затем направьте их в xargs:

svn-empties | xargs svn rm

Этот скрипт стал очень полезным для меня при использовании git-svn (спасибо!). Поскольку git не отслеживает пустые каталоги, я могу получить много пустых каталогов в хранилище Subversion. Я svn co отдельный экземпляр хранилища и запускаю svn-empties | xargs svn rm периодически. Использование Subversion в первую очередь не было моим решением;)

2

Я просто наткнулся на это, и я использовал этот скрипт, но изменил его, чтобы правильно рассматривать пустые каталоги только с .svn и без других файлов, скрытых или нормальных.

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

for folder in $(find -type d ! -path *.svn*); do
  if [ "`find $folder ! -path *.svn* ! -path $folder | wc -l`" -eq 0 ]; then
    svn rm $folder
  fi
done
1

Если вы можете, вы, конечно, можете сначала удалить все папки .svn . Недостаток: вы потеряете информацию контроля версий, если кто-то использует SVN. Если кто-то использует SVN, то не стоит просто удалять эти папки (или на самом деле вы должны удалить их и из SVN, так как SVN отслеживает папки и файлы).

Если это невозможно, я бы пошел со сценарием маршрута:

for folder in $(find . -type d); do
 if [ "`ls $folder | wc -l`" -eq 0 ]; then
  echo "I am going to delete $folder"
 fi
done

Сначала попробуйте пробный запуск, потому что может быть что-то удивительное. Тогда вы можете изменить rm -r вместо этого echo .

Однако обратите внимание, что это удалит все папки только с точечными файлами (поэтому, например, a/.this_is_super_important будет удален, если нет других файлов или папок).

0
  1. решена проблема: пробелы в Path
  2. Можно вызвать скрипт с параметром PATH, например так:

svn-empties YOU_WANT_TO_SEARCH_PATH

C_IFS=$IFS

IFS=$'\n'

for folder in $(find "$1" -depth -type d ! -path *.svn*|sort -r); do
  counts=$(find "$folder" -type f ! -path *.svn* ! -path $folder | wc -l)

  if [ $counts -eq 0 ]; then
    echo $folder
  fi

done

IFS=$C_IFS
0

Чтобы избежать проблем с пробелами, find и магией IFS (имена файлов могут также содержать символы новой строки, поэтому IFS=$'\n' не является серебряной пулей), можно использовать глобусы и массивы.

#!/bin/bash
search_dir=${1:-.}
shopt -s globstar dotglob
for svn_dir in "$search_dir"/**/.svn/; do
    base_dir=${svn_dir%/.svn/}
    base_dir_contents=("$base_dir"/*)
    if [ ${#base_dir_contents[@]} -eq 1 ]; then
        printf 'The directory "%s" only contains ".svn/".\n' "$base_dir"
    fi
done
  • Сценарий принимает необязательный аргумент пути или использует текущий путь по умолчанию, если он отсутствует.
  • globstar включает конструкцию обхода каталогов ** .
  • dotglob включает в себя скрытые файлы в виде звездочек.
  • Глобус for должен быть защищен от любых проблемных символов имени каталога. Глобусы всегда будут безопасно расширяться в Bash, что не относится к ls , find и т.д. Конечная косая черта гарантирует, что мы сопоставляем только папки с именами .svn а не обычные файлы (хотя в настоящем угловом случае).
  • Имена файлов, содержащихся в папке с соответствующим .svn , помещаются в массив. Если количество элементов в этом массиве равно 1 (то есть папка .svn которую мы по построению знаем * есть), то это то, что мы ищем.

Он использует только встроенные модули Bash и, следовательно, должен быть быстрее, чем выдавать дополнительные системные вилки для find , но, скорее всего, разница не заметна, и в любом случае основным узким местом будет ввод / вывод.


*: Незначительный sidenote (также относится и к другим решениям): возможное состояние гонки, если, например, в каталоге есть только .svn и файл foo , а каталог .svn удаляется между аргументом for и массивом что также приведет к удалению foo . Однако, если кто-то со злым умыслом имеет право удалять файлы в файловой системе, игра, вероятно, уже потеряна, и их можно было бы удалить напрямую, чем с помощью временных атак.


Еще одно быстрое упоминание заключается в том, что другие ответы должны цитировать их расширения *.svn* . В противном случае команда find не будет выполнена, если текущая папка содержит файл, соответствующий этому глобанту:

$ mkdir foo && cd foo
$ mkdir -p test1/.svn test2
$ find -type d ! -path *.svn*
.
./test1
./test2
$ touch foo.svnbar
$ find -type d ! -path *.svn*
.
./test1
./test1/.svn
./test2
$ find -type d ! -path "*.svn*"
.
./test1
./test2

Без кавычек *.svn* будет преждевременно расширен оболочкой до foo.svnbar .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .