Я пытаюсь удалить все пустые папки в каталоге. Тем не менее, find . -type f -empty
не находит ничего, потому что каждая папка содержит скрытую папку .svn
.
Как я могу обойти это?
Я пытаюсь удалить все пустые папки в каталоге. Тем не менее, find . -type f -empty
не находит ничего, потому что каждая папка содержит скрытую папку .svn
.
Как я могу обойти это?
Незначительные изменения (просто распечатайте каталог и отправьте в 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 в первую очередь не было моим решением;)
Я просто наткнулся на это, и я использовал этот скрипт, но изменил его, чтобы правильно рассматривать пустые каталоги только с .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
Если вы можете, вы, конечно, можете сначала удалить все папки .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
будет удален, если нет других файлов или папок).
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
Чтобы избежать проблем с пробелами, 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
.