Hapus semua direktori dari dalam direktori induk kecuali satu dan turunannya

8

struktur direktori

Saya ingin menghapus direktori B dan D. Tetapi saya ingin menyimpan C dan semua file turunan dan direktori. Apa perintah untuk menghapus semua direktori anak-anak dari direktori induk kecuali satu direktori dan anak-anaknya.

Bantuan dihargai.

Joe Saad
sumber
direktori mana yang ingin Anda hapus kosong?
Penatua Geek
Bagaimana dengan file yang terletak langsung di direktori induk ( Adalam contoh Anda)? Hapus juga atau simpan?
Byte Commander
Yang ditanyakan Byte Commander adalah, apakah ada file di A? atau hanya direktori? Apakah Anda ingin file biasa di direktori A dihapus atau hanya?
Sergiy Kolodyazhnyy

Jawaban:

6

Apa yang Anda inginkan adalah perintah ini:

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

Demo:

# 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/

Penjelasan:

  • find DIRECTORY panggil perintah find untuk beroperasi pada DIREKTORI
  • -mindepth 1 : hanya bekerja dengan isi direktori, hindari direktori itu sendiri yang level 0
  • -maxdepth 1: mencegah turun ke subdirektori ( rm -rftoh bersifat rekursif, jadi kami tidak perlu turun ke subdirektori untuk menghapusnya)
  • -type d : hanya mencari direktori
  • -not \( -name "keepMe" \) abaikan item dengan nama yang ingin Anda simpan
  • -exec rm -rf {} \; melakukan penghapusan pada setiap item yang ditemukan
Sergiy Kolodyazhnyy
sumber
Penjelasan yang bagus. Terlalu banyak penekanan tombol untuk saya ...
Penatua Geek
1
findadalah teman yang baik di sini, tetapi Bash fordan testteman yang lebih baik ...>: - D
Byte Commander
8

Menggunakan fitur glob bash shell yang diperluas (yang diaktifkan secara default di instalasi Ubuntu saat ini), diberikan

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

5 directories, 0 files

Anda dapat mengatasi segala sesuatu yang dikecualikan Cdan isinya menggunakan ekspresi glob A/!(C)yaitu

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

Jadi untuk menghapus semuanya kecuali direktori Cdan isinya Anda cukup menggunakan

rm -rf A/!(C)

pergi

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

3 directories, 0 files
Steeldriver
sumber
Sungguh menakjubkan mengetahui tentang fitur ini. Ini bekerja dengan baik setelah saya ssh dan secara manual menjalankan tetapi saya mendapatkan `" -bash: baris 1: kesalahan sintaks dekat token yang tidak terduga ('"ketika saya menjalankannya dari jarak jauh melalui ssh $VM_ADDRESS "rm -rf $APP_FOLDER/!(node_modules)". Ada ide? Terima kasih banyak.
Renato Gama
@renatoargh extglobopsi shell hanya diaktifkan untuk shell interaktif - tidak yakin apakah Anda dapat memaksa sshuntuk melakukannya
steeldriver
5

Salah satu cara mudah adalah menggunakan trash-cli

Anda dapat menginstalnya dengan sudo apt-get install trash-cli

Setelah terinstal, Anda dapat menavigasi ke direktori induk A dengan cd /Adan kemudian mengeluarkan perintah di trash B Dmana B dan D adalah direktori yang ingin Anda hapus (mereka akan berakhir di tempat sampah untuk drive mereka berada di jadi jika Anda membuat kesalahan Anda bisa pulihkan file)

Diuji di bawah Ubuntu 16.04 dan 14.04

Penatua Geek
sumber
Mungkinkah ini disederhanakan dengan sesuatu seperti trash ! C?
Sergiy Kolodyazhnyy
@Serg Nggak trash: cannot trash non existent ! '`
Penatua Geek
@Serg dan C dihancurkan ...
Penatua Geek
Ditemukan: stackoverflow.com/q/216995/3701431 Perlu diaktifkan extglob.
Sergiy Kolodyazhnyy
@Ergerg Tergantung pada pekerjaan yang ada di tangan yang mungkin cukup berguna! ;-)
Penatua Geek
4

Cukup gunakan Bash's forloop dan testuntuk menyaring direktori yang diinginkan dan rm -rfperintah untuk menghapus direktori secara rekursif, seperti ini:

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

Ini mengulangi semua elemen (file dan direktori) di dalam /path/to/parent/dan menghapus elemen secara rekursif jika namanya tidak sama dengan dir_survive. Jika direktori induk adalah direktori saat ini, Anda hanya boleh menulis *sebagai path.

Jika Anda tidak yakin dan ingin menguji elemen mana yang akan dihapus terlebih dahulu tanpa mengambil tindakan apa pun, cukup ganti rm -rfdengan perintah di atas dengan echodan itu hanya akan menampilkan kandidat yang dihapus.

Berikut ini contoh yang dijalankan:

$ 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
Komandan Byte
sumber