На терминале Mac OS X, как мы можем рекурсивно удалить все файлы и папки, включая скрытые, кроме одного каталога?

Спасибо.

2 ответа2

3

ВНИМАНИЕ: запуск любой команды для рекурсивного удаления файлов опасен. Всегда, всегда проверяйте, прежде чем вслепую запускать такие опасные команды, и никогда не запускайте их как пользователь root (или с sudo и т.д.), Никогда .

Это относительно легко сделать с небольшим количеством bash, вы можете даже сделать это аргументом, который вы передаете, если вы собираетесь делать это много. Но, на этот раз, попробуйте что-то вроде моего простого теста ниже.

Сначала я создам несколько папок для тестирования:

cd test; mkdir -p one two three four five six .hidden

Затем я создам скрипт bash (в данном случае rm.bash) со следующим содержимым:

for i in `ls -A`
do      
        if [ ! "${i}" == 'three' ] && [ ! "${i}" == $0 ]; then 
                echo "would delete ${i}" 
        else    
                echo "not deleting ${i}" 
        fi
done

Для объяснения: ls -A распечатает все файлы, кроме текущей папки и родительского файла (. И ..). Мы используем этот список с циклом for для перебора всего содержимого. Я решил (произвольно), что единственная папка, которую мы оставим, это "три" и что я не хочу удалять сам скрипт rm.bash .

Следовательно, условие if будет истинным только в том случае, если рассматриваемый файл / папка не назван ни three ни rm.bash ($0 означает, что это работает независимо от того, как вы называете файл).

Вместо того, чтобы запускать это немедленно с помощью команды rm -rf ${i} (что опасно), я вместо этого использовал пару команд echo чтобы показать, что будет удалено, а что нет.

Вот мой пример вывода:

would delete five
would delete four
would delete one
not deleting rm.bash
would delete six
not deleting three
would delete two

После того, как вы убедились, что скрипт выполняет правильные действия, а не удаляет вещи, которые он не должен и т.д., Вы можете изменить код так:

for i in `ls -A`
do      
        if [ ! "${i}" == 'three' ] && [ ! "${i}" == $0 ]; then 
                rm -rf ${i} 
        fi
done
1

Альтернатива. Те же предостережения, что и в ответе @Adam C; не запускайте это без тестирования.

Некоторые демонстрационные данные:

$ mkdir testing; cd testing
$ mkdir one two three four "fi ve"
$ touch one/one.txt two/two.txt three four/keep.txt fi\ ve/.hidden

Имитация удаления всех, кроме четырех /

$ find . -mindepth 1  -path ./four -prune -o -exec echo would remove "{}" +

Выход:

would remove ./fi ve ./fi ve/.hidden ./two ./two/two.txt ./one ./one/one.txt ./three

Заметки:

-mindepth 1  prevents including /.
Prune removes path four/ from processing, or...
-o means "or" (either prune the left, or exec on the right)
High speed / low resource use:
  find will stop processing a tree once pruned (no wasted operations)
  One xargs-style list is built (with +), removal happens in one command.
  To process one at a time, replace + with \;
Spaces are handled correctly within " "
-delete is shorter but may not operate on directories
find won't follow symlinks by default

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