Belirli bir ada sahip klasör dışındaki tüm klasörleri silme


18

Günlük bir komut dosyası kullanarak bir klasör içindeki tüm klasörleri silmem gerekiyor. O gün için klasörün bırakılması gerekiyor.

'Myfolder' klasörü 3 alt klasöre sahiptir: 'test1', 'test2' ve 'test3' 'test2' hariç hepsini silmem gerekiyor.

Burada tam adı eşleştirmeye çalışıyorum:

find /home/myfolder -type d ! -name 'test2' | xargs rm -rf

VEYA

find /home/myfolder -type d ! -name 'test2' -delete

Bu komut her zaman 'myfolder' ana klasörünü de silmeye çalışır! Bundan kaçınmanın bir yolu var mı ?


6
Unix ve Linux'ta, "klasörler" değil, bu "dizinler" diyoruz.
tchrist

1
Kabuğunuza bağlı olarak, şu !operatörü belirtmeniz gerekebilir : \!veya '!'.
Toby Speight

Yanıtlar:


32

Bu, ./myfolderdışındaki tüm klasörleri silecek ./myfolder/test2ve tüm içeriği korunacaktır:

find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?' -delete

Nasıl çalışır

  • find bir find komutu başlatır.
  • ./myfolderdizine ./myfolderve içindekilere başlamayı söyler .

  • -mindepth 1./myfolderkendisini eşleştirmek için değil , sadece altındaki dosyalar ve dizinler.

  • ! -regex '^./myfolder/test2\(/.*\)?' bulmayı !normal ifadeyle eşleşen herhangi bir dosya veya dizini hariç tutmayı ( ) söyler ^./myfolder/test2\(/.*\)?. ^yol adının başlangıcıyla eşleşir. İfade (/.*\)?(a) bir eğik çizgi ve ardından herhangi bir şeyle veya (b) hiçbir şeyle eşleşmez.

  • -delete eşleşen (yani hariç tutulmayan) dosyaları silmeyi söyler.

Misal

Şuna benzeyen bir dizin yapısı düşünün;

$ find ./myfolder
./myfolder
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2

-deleteNeyle eşleştiğini görmek için find komutunu (onsuz ) çalıştırabiliriz :

$ find ./myfolder -mindepth 1 ! -regex '^./myfolder/test2\(/.*\)?'
./myfolder/test1
./myfolder/test1/dir1
./myfolder/test1/dir1/test2
./myfolder/test1/dir1/test2/file4
./myfolder/test1/file1
./myfolder/test3
./myfolder/test3/file3

Kalan dosyalara bakarak bunun işe yaradığını doğrulayabiliriz:

$ find ./myfolder
./myfolder
./myfolder/test2
./myfolder/test2/file2
./myfolder/test2/dir2

1
Alt dizinleri yalnız -prunebırakmak için alternatif test2/*/: geri dönün rm -rve ekleyin -maxdepth 1.
Toby Speight

@Isaac OK. Bitti. (Ayrıca, mükemmel cevabınız için +1.)
John1024

Mükemmel iş !, ama üzgünüm: içindeki tüm dosyaları kaldıracak ./myfolder. Yalnızca dizinler-type d için eksik (IMvhO) gerekir .
NotAnUnixNazi

Tamam, bu istediğiniz gibi çalışmalıdır:find ./myfolder -depth -mindepth 1 -maxdepth 1 -type d ! -regex '^./myfolder/test2\(/.*\)?'
NotAnUnixNazi

10

Bash kullanma :

shopt -s extglob
rm -r myfolder/!(test2)/

Misal:

$ tree myfolder/
myfolder/
├── test1
│   └── file1
├── test2
│   └── file2
└── test3
    └── file3

$ echo rm -r myfolder/!(test2)
rm -r myfolder/test1 myfolder/test3
$ rm -r myfolder/!(test2)
$ tree myfolder/
myfolder/
└── test2
    └── file2

1 directory, 1 file

5

tl; Dr.

find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 \
     -exec echo rm -rf '{}' \;

Dosya listesinden memnunsanız yankıyı kaldırın.


Kullanılması -mindepth 1, üst dizinin seçili olmamasını sağlar.

$ find ./myfolder -mindepth 1 -type d
./myfolder/test2
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

Ama -not -name test2olacak değil subdirs içine önlemek test2:

$ find ./myfolder -mindepth 1 -type d -not -name 'test2'
./myfolder/test2/one
./myfolder/test2/two
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

Bunu yapmak için, kuru erik gibi bir şeye ihtiyacınız var:

$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -print
./myfolder/test
./myfolder/test/a1
./myfolder/test/a1/a2
./myfolder/test/a1/a2/a3

Ama kullanmayın deleteo da anlaşılacağı gibi, depthve bu en uzun yoldan silmeye başlar:

$ find ./myfolder -depth -mindepth 1 -name test2 -prune -o -type d -print
./myfolder/test/a1/a2/a3
./myfolder/test/a1/a2
./myfolder/test/a1
./myfolder/test

Ya kullanın rm -rf( echogerçekten silmek istiyorsanız kaldırın ):

$ find ./myfolder -mindepth 1 -name test2 -prune -o -type d -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test
rm -rf ./myfolder/test/a1
rm -rf ./myfolder/test/a1/a2
rm -rf ./myfolder/test/a1/a2/a3

Ya da, aynı zamanda kullanmak maxdepthihtiyacınız olan tüm dizinleri (ve her şey içini) silin (kaldırmaktır eğer echogerçekten silme için):

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -exec echo rm -rf '{}' \;
rm -rf ./myfolder/test

Bir -deletedizin boş değilse yine başarısız olur:

$ find ./myfolder -mindepth 1 -maxdepth 1 -type d -not -name test2 -delete
find: cannot delete ‘./myfolder/test’: Directory not empty

2

Zsh kullanıyorsanız, şunları yapabilirsiniz:

setopt extended_glob # if you don't have it enabled

rm -rf myfolder/^test2

0

Aşağıdaki komutla test edildi ve iyi çalıştı

find  /home/myfolder -maxdepth 1 -type d ! -iname test2 -exec rm -rvf {} \;

OP ile aynı problemle karşılaştınız; komut satırında listeleme / home / klasör (kritik olmayan -mindepth 1) listenin en üst dizinin tüm ölçütlerle eşleşmesini sağlar (bu bir dizin ve "test2" olarak adlandırılmaz) ve böylece silinir.
Jeff Schaller
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.