Как рекурсивно удалить подкаталоги и файлы, но не первый родительский каталог?

13

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

find '/target/directory/' -type d -name '*' -print0 | xargs -0 rm -rf

Однако я не хочу, чтобы целевой каталог удалялся. Как я могу удалить только файлы в целевой папке, подкаталогах и их содержимом?

Майкл Прескотт
источник

Ответы:

11

Предыдущий ответ почти правильный. Однако вы не должны заключать в кавычки символы оболочки, если хотите, чтобы они работали. Итак, это команда, которую вы ищете:

rm -rf "/target/directory with spaces/"*

Обратите внимание, что * находится вне двойных кавычек. Эта форма также будет работать:

rm -rf /target/directory\ with\ spaces/*

Если у вас есть *кавычки, как показано выше, то он будет пытаться удалить только один файл с буквальным именем *внутри целевого каталога.

pioto
источник
1
Это не работает со скрытыми файлами и папками. Я должен был сделать это еще раз с
The Unfun Cat
8

Еще три варианта.

  1. Используйте findс -mindepth 1и -delete:

    −mindepth уровни
    Не применять какие-либо тесты или действия на уровнях меньше, чем уровни (неотрицательное целое число).
    −mindepth 1 означает обрабатывать все файлы, кроме аргументов командной строки.

    -Удалите
    Удалить файлы; истина, если удаление прошло успешно. Если удаление не удалось, выдается сообщение об ошибке. Если -delete терпит неудачу, состояние выхода find будет отличным от нуля (когда оно в конечном итоге завершится). Использование -delete автоматически включает параметр -depth.
    Тщательно проверьте с опцией -depth перед использованием этой опции.

    # optimal?
    # -xdev      don't follow links to other filesystems
    find '/target/dir with spaces/' -xdev -mindepth 1 -delete
    
    # Sergey's version
    # -xdev      don't follow links to other filesystems
    # -depth    process depth-first not breadth-first
    find '/target/dir with spaces/' -xdev -depth -mindepth1 -exec rm -rf {} \;
    



2. Используйте find, но с файлами, а не каталогами. Это позволяет избежать необходимости rm -rf:

    # delete all the files;
    find '/target/dir with spaces/' -type f -exec rm {} \;

    # then get all the dirs but parent
    find '/target/dir with spaces/' -mindepth 1 -depth -type d -exec rmdir {} \;

    # near-equivalent, slightly easier for new users to remember
    find '/target/dir with spaces/' -type f -print0 | xargs -0 rm
    find '/target/dir with spaces/' -mindepth 1 -depth -type d -print0 | xargs -0 rmdir



3. Идите дальше и удалите родительский каталог, но создайте его заново. Вы можете создать функцию bash, чтобы сделать это с помощью одной команды; вот простой однострочник:

    rm -rf '/target/dir with spaces' ; mkdir '/target/dir with spaces'
шарлатан
источник
2

Как насчет

rm -rf /target/directory\ path/*

Если могут быть файлы, начинающиеся с. в целевом каталоге.

rm -rf "/target/directory path/*" "/target/directory path/.??*"

Эта секунда будет соответствовать всему, начинающемуся с., Кроме. и .. Это не удастся для имен, как .a, но это не очень распространено. Это может быть изменено в случае необходимости, чтобы покрыть все случаи.

KeithB
источник
Я попробовал оба, и они не работают для меня. Возможно, потому, что в моем пути к целевому каталогу есть пробелы? rm -rf '/ target / directory path / *' Ошибка не выдается, но подкаталоги остаются.
Майкл Прескотт
Вам нужно экранировать пробелы, либо с обратной косой чертой (\) перед пробелом, либо заключив все имя каталога в кавычки ("). Я отредактировал примеры, чтобы показать это.
KeithB
Спасибо, я попытался это сделать, как показано в моем предыдущем комментарии, и до сих пор не пошел. (Я использую OS X, это имеет значение?)
Майкл Прескотт
OS X должна работать нормально, вот что я использую. Убедитесь, что вы не используете обратную косую черту и кавычки. Только один или другой.
KeithB
Да, просто используя цитаты. Если я удаляю * и поэтому я использую только rm -rf "/ target / directory path /", каталог "path path" будет удален вместе с подкаталогами "path path". Если я использую rm -rf "/ target / directory path / *", ничего не происходит.
Майкл Прескотт
2
find /target/directory/ -xdev -depth -mindepth 1 -exec rm -Rf {} \;
Сергей
источник