Видаліть усі каталоги з батьківського каталогу, крім одного та його нащадків


8

структура каталогів

Я хочу видалити каталоги B і D. Але я хочу зберегти C і всі його потомкові файли та каталоги. Яка команда видалити всі дочірні каталоги з батьківського каталогу, крім одного каталогу та його дочірніх.

Допомога оцінена.


чи є каталоги, які ви хочете видалити порожніми?
Старійшина Гік


А що з файлами, безпосередньо розташованими в батьківському каталозі ( Aу вашому прикладі)? Видалити їх чи зберегти?
Командир байт

Що запитує командир байтів, чи є файли в A? чи лише каталоги? Ви хочете регулярні файли у видалених або лише каталогах?
Сергій Колодяжний

Відповіді:


6

Що ви хочете, це ця команда:

find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;

Демонстрація:

# List what's inside directory we want to remove
$ ls
file1  file2  keepMe/  removeA/  removeB/
# Testing what find gives without removing
$ find ~/TESTDIR -mindepth 1 -type d -not \( -name "keepMe" \)               
/home/xieerqi/TESTDIR/removeA
/home/xieerqi/TESTDIR/removeB
# Actual removal and testls
$ find ~/TESTDIR -mindepth 1 -maxdepth 1 -type d -not \( -name "keepMe" \) -exec rm -rf {} \;
$ ls
file1  file2  keepMe/

Пояснення:

  • find DIRECTORY команда пошуку виклику для роботи в режимі DIRECTORY
  • -mindepth 1 : працюйте лише зі вмістом каталогу, уникайте самого каталогу, який є рівнем 0
  • -maxdepth 1: запобігає спуску в підкаталоги ( rm -rfвсе одно є рекурсивним, тому нам не потрібно спускатися в підкаталоги, щоб видалити їх)
  • -type d : шукайте лише каталоги
  • -not \( -name "keepMe" \) ігноруйте елемент з ім'ям, яке ви хочете зберегти
  • -exec rm -rf {} \; виконати видалення кожного знайденого предмета

Чудове пояснення. Занадто багато для мене натискань на клавіші ...
Старійшина Гік

1
findтут хороший друг, але Баш forі testкращі друзі ...>: - D
Байт командир

8

Використання розширених глобальних функцій оболонки bash (які включені за замовчуванням у поточних установках Ubuntu)

$ tree A
A
├── B
├── C
│   ├── ac1
│   └── ac2
└── D

5 directories, 0 files

Ви можете вирішити все, що виключає, Cта його вміст, використовуючи вираз glob, A/!(C)тобто

$ echo A/!(C)
A/B A/D

Тому для видалення всього, крім каталогу Cта його вмісту, ви можете просто скористатися

rm -rf A/!(C)

залишаючи

$ tree A
A
└── C
    ├── ac1
    └── ac2

3 directories, 0 files

Про цю особливість дивно знати. Він відмінно працює , коли я SSH і запустити вручну , але я отримую `« -bash: рядок 1: помилка синтаксису близько несподіваною лексеми , ('"коли я запустити його віддалено через ssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)"Будь-які ідеї , спасибі багато.?.
Ренато Гама

@renatoargh extglobопція оболонки увімкнена лише для інтерактивних оболонок - не впевнений, чи можна змусити sshце зробити
steeldriver

5

Одним із простих способів було б використання кошика для сміття

ви можете встановити його sudo apt-get install trash-cli

Після встановлення ви можете перейти до батьківського каталогу A з, cd /Aа потім видати команду, trash B Dде B і D - це каталоги, які ви хочете видалити (вони опиняться у відро для сміття для накопичувача, на якому вони знаходяться, тому якщо ви помилитесь, ви можете відновлення файлів)

Тестували під Ubuntu 16.04 та 14.04


Чи можна це спростити чимось на кшталт trash ! C?
Сергій Колодяжний

@Serg Nope trash: cannot trash non existent ! ''
Старійшина

@Serg і C потрапляють у сміття ...
Старійшина

Знайдено: stackoverflow.com/q/216995/3701431 Хоча це вимагає ввімкнення extglob.
Сергій Колодяжний

@ Сергій Залежно від роботи, яка може бути дуже корисною! ;-)
Старійшина Гік

4

Просто використовуйте forцикл Баша та testфільтруйте потрібні каталоги та rm -rfкоманду для рекурсивного видалення каталогів, як це:

for x in /path/to/parent/*; do test "$x" != "dir_survive" && rm -rf "$x"; done

Це повторює всі елементи (файли та каталоги) всередині /path/to/parent/та видаляє елемент рекурсивно, якщо його ім'я не дорівнює dir_survive. Якщо батьківський каталог є поточним каталогом, ви можете записувати лише *як шлях.

Якщо ви не впевнені в собі і хочете перевірити, які елементи будуть видалені спочатку, не вживаючи жодних дій, просто замініть rm -rfна команду, вказану вище, echoі вона видасть лише кандидатів видалення.

Ось приклад запуску:

$ tree
.
├── dir1
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
├── dir2
│   ├── subdir1
│   │   ├── file1
│   │   └── file2
│   └── subdir2
│       ├── file1
│       └── file2
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

9 directories, 12 files

$ for x in *; do test "$x" != "dir_survive" && rm -rf "$x"; done

$ tree
.
└── dir_survive
    ├── subdir1
    │   ├── file1
    │   └── file2
    └── subdir2
        ├── file1
        └── file2

3 directories, 4 files
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.