Bagaimana cara mengecualikan beberapa file dari mekanisme ekspansi nama file di bash?

14

Saya memiliki direktori sistem file ubuntu di direktori root dan saya tidak sengaja menyalin ratusan file ke direktori root.

Saya secara intuitif mencoba menghapus file yang disalin dengan mengecualikan sistem file seperti

rm -rf !{bin,sbin,usr,opt,lib,var,etc,srv,libx32,lib64,run,boot,proc,sys,dev} ./.

tapi itu tidak berhasil. Apa cara yang tepat untuk mengecualikan beberapa direktori sambil menghapus keseluruhannya?

SUNTING: Jangan pernah coba perintah apa pun di sini tanpa tahu harus berbuat apa!

kenn
sumber
1
Shell apa yang Anda gunakan? Globase nama file tergantung pada shell ketika melakukan hal-hal mewah seperti itu.
Kusalananda
2
Bukan jawaban, tapi saya akan gunakan misalnya mc. Pilih segala sesuatu dengan *, lalu hapus pilihan file -atau dengan Insertkunci tertentu.
pbm
1
Bisakah Anda jelaskan apa itu 'mc'?
MikeP
@ Kusalananda itu/bin/bash
kenn
3
@MikeP: mcadalah Midnight Commander, tiruan Norton Commander yang sangat berguna. Ini berjalan di terminal. (Baik Midnight Commander dan Norton Commander adalah contoh dari apa yang disebut file manager ortodoks .)
AlexP

Jawaban:

21

Karena Anda menggunakan bash:

shopt -s extglob
echo rm -rf ./!(bin|sbin|usr|...)

Saya sarankan untuk menambahkan echo di awal baris perintah ketika Anda menjalankan sesuatu yang berpotensi meledakkan seluruh sistem. Hapus jika Anda senang dengan hasilnya.

Catatan: Perintah di atas tidak akan menghapus file tersembunyi (yang namanya dimulai dengan titik). Jika Anda ingin menghapusnya juga, aktifkan juga dotglobopsi:

shopt -s dotglob
jimmij
sumber
Saya menggunakannya untuk membersihkan sistem file dengan sukses. Awalnya saya mengujinya di direktori. Saya juga mencoba rm -rf ./!(bin,sbin,..)koma terpisah, tetapi menghapus semua direktori.
kenn
Apa itu !(...)sintaks? Dari contoh yang saya pikir secara intuitif ls ./!(*/)akan daftar file saja, tetapi tidak berfungsi seperti itu.
giusti
@giusti Sintaks ini adalah pencocokan pola yang diperluas dalam mekanisme ekspansi nama file - Anda akan menemukan deskripsinya di manual bash di bawah bab Perluasan Pathname. Itu tidak dapat digunakan untuk mengecualikan jenis file, hanya nama, seperti dengan bintang *atau gumpalan lainnya.
jimmij
12

Perintah ini akan menampilkan semua non-direktori di /:

find / -maxdepth 1 -type f

Setelah Anda benar-benar memastikan tidak ada file yang ingin Anda simpan, Anda dapat menggunakan:

find / -maxdepth 1 -type f -delete

Lebih aman, akan memindahkannya ke tempat lain untuk memastikan Anda tidak menghapus sesuatu yang ingin Anda pertahankan:

mkdir /root/preserve
find / -maxdepth 1 -type f -exec mv -- "{}" /root/preserve/\;

Jika, selain file, Anda juga memiliki direktori yang telah Anda tambahkan ke root sistem file, ini bisa otomatis dengan mengecualikan direktori LSB dari otomatis mvatau rm, tapi jujur, karena kita sedang berurusan dengan membersihkan hal-hal di root dari filesystem, saya akan sangat menyarankan Anda mempertimbangkan untuk melakukannya secara manual jika memungkinkan.

Jika ini tidak layak, sesuatu seperti ini dapat melakukan trik:

#!/bin/bash
declare -a excludes
for item in root sys 'lost+found' mnt home proc etc opt boot lib lib64 libx32 sbin media srv dev var usr bin tmp run; do
    excludes+=("$item")
done
if ! [[ -d /root/preserve ]]; then
    mkdir -p /root/preserve
fi
IFS="\n"
for item in find / -type d -maxdepth 1; do
    really=true
    for exclude in ${excludes[@]}; do
        if [[ "$exclude" == "${item#/}" ]]; then
            really=false
        fi
    done
    if [[ "true" == "$really" ]]; then
        mv -- "$item" /root/preserve/
    fi
done

Setelah Anda lulus tes menjerit (yaitu sistem Anda masih berjalan dan Anda tidak menjerit kesedihan), Anda dapat menghapus konten /root/preserve/.

Catatan penting: Apa pun yang Anda lakukan, jangan pernah berpikir untuk menjalankan permutasi rm -fr [ANYTHING GOES HERE] /.

DopeGhoti
sumber
solusi Anda hanya menghapus file tetapi ada juga folder di sekitar.
kenn
1
Terlalu sering, saya telah mendengar jeritan cemas dari orang yang bertujuan buruk rm. Seperti skrip dengan rm -fr $somepath/dengan somepathtidak diinisialisasi di dalamnya. Saya bisa lebih jauh dalam mengungkapkan betapa seriusnya hal ini, tetapi memilih untuk tetap ramah keluarga dalam peringatan saya.
DopeGhoti
3

Ini harus menyelesaikan pekerjaan (meskipun tidak dengan cara yang sama seperti yang diminta OP):

ls -1 >1.txt
pico 1.txt 

hapus semua file / direktori yang ingin Anda simpan

xargs rm < 1.txt

Jika semua file Anda memiliki format nama, tanggal, atau hal lain yang sama, maka ada metode lain.

Saya akan melihat inode - dan melihat apakah mereka berurutan melalui ls-i | sort dan jika ya, maka file baru akan memiliki inode yang lebih besar. Kemudian menggunakan jenis proses yang sama seperti di atas ...

ls -iF1 | sort |cut -c10- | grep -vE "\/|\@" >i.txt   #This part removes entries that are not regular files, such as directories and links.  
pico i.txt
xargs rm < i.txt

dalam perintah cut di atas, periksa daftar inode Anda terlebih dahulu untuk memastikan itu jumlah yang tepat.

MikeP
sumber