Belirli bir aralıktaki numaralı dosyaları nasıl silebilirim?


16

Ben folderAbaşlayan bir sayı dizisi ile bazı dosyaları var a_000000. Yapmak istediğim belirli bir sayıdan başlayarak dosyaları silmek: diyelim ki a_000750buradaki dosyaların sonuna kadar folderA. Herkes kabuk betiği kullanarak bunu nasıl tavsiye lütfen?


Tüm bu dosya adlarının 6 basamaklı sonekleri olduğunu varsayabilir miyim?
muru

evet onlar :) a_000000 bir sayı kadar başlıyorlar
Tak

5
rm a_000[89]* a_0007[5-9]*?
Rinzwind

@Rinzwind bu komutu açıklayabilir misiniz?
Tak

2
@ user1460166 a_000[89]*her dosya başlangıcını içerir a_0008ya a_0009ve a_0007[5-9]*ile başlayan her dosyayı içeren a_0007ve daha sonra herhangi bir şey tarafından takip 5 ile 9 arasında bir sayı içeren.
muru

Yanıtlar:


35

Aralığın sonunu bildiğinizi veya tahmin edebileceğinizi varsayarsak, destek genişletmelerini kullanabilirsiniz :

rm a_{000750..000850}

Yukarıdakiler a_000750 ve a_000850 dahil (dahil) 101 dosyayı silecek (ve mevcut olmayan dosyalara atıfta bulunan dosya adlarından şikayet edecek). Bunun için çok fazla dosyanız varsa, şunu kullanın find:

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

Burada, findeşleşen tüm dosyaları listeler a_*. Liste, whileher dosya adının değişkene okunduğu bir döngüye aktarılır $file. Ardından, bash'ın dize düzenleme özelliklerini kullanarak , sayısal kısım (find dosyaları yazdırır ./file, böylece ${file#./a_}yalnızca sayıyı yazdırır) 000750veya daha büyükse, dosya silinir. -vBöylece çıkarıldı hangi dosyaları görebilirsiniz sadece yoktur.

Yukarıdakilerin aklı başında dosya adlarını aldığını unutmayın. Adlarınızda boşluklar, yeni satırlar veya başka garip karakterler varsa, bunun yerine şunu kullanın:

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

Neden kaçının [[?
muru

1
@muru neden kullanıyorsunuz? mesela [[burada işleri basitleştirmiyor [[ "${file#./a_}" > 000749 ]], kısaltmıyor bile. Gereksiz sözdizimini kullanmayı sevmiyorum ve bu daha basit kabuklarda bile çalışacak dash.
terdon

Çünkü [[boşlukları ve tuhaflıkları daha iyi işler ( >her ikisi için de umurumda değil).
muru

1
@muru evet, ama [değişkeni benim gibi teklif ederseniz, çok daha fazla kabuk üzerinde çalışır ve daha basitse iyidir.
terdon

Eğer ısrar ediyorsan. Benim sorunum değil.
muru

3

Böyle bir şey yapabilirsiniz:

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;

Veya:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

İlk yöntem sabit bir önek varsayar, onu kaldırır ve değeri kontrol eder.

İkinci yöntem, sabit uzunluklu bir sonek (ve ortak bir sabit önek) varsayar ve bu gerçeğe dayanır; ve daha 201önce 31sözlükbilimsel olarak gelirken , daha önce değil 031.

Bunu echokomutla sınayın ve doğru dosyaları listelediğinden emin olduktan sonra bunu rmkullanın.


hiçbiri çalışmıyor: /
Tak

@ user1460166 ah, bunun nedeni muhtemelen normal ifade eşleşmesidir. Ben güncelleyeceğim.
muru

hala çalışmıyor. btw, dosyalar .png :)
Tak

@ user1460166 nasıl çalışmadığını söyleyebilir misiniz?
muru

Terminali açıyorum, cd'yi klasöre veriyorum, sonra satırınızı kopyalayıp yapıştırıyorum, ancak dosyalar silinmiyor
Tak

0

POSIX kabuk çözümü

terdon'un ilk çözümü , bir özelliği olan küme ayracı genişlemesine dayanır bashve kshancak Ubuntu'da sembolik olarak kullanılan standart /bin/shkabukta kullanılamaz /bin/dash.

/bin/shKomut dosyalarınızın taşınabilirliğine güvenmeniz gereken durumlarda , genellikle buna yaklaşmanın iki yolu vardır. Biri globbing yoluyla olurdu. Sadece cd folderAve oradan kaç rm a_*. Diğer bir yol, while <CONDITION>;do ...donekabuk dilinde kullanarak döngü alternatifi için bir C stili uygulamak ve sayıları şu şekilde biçimlendirmek olacaktır printf:

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

Burada kullandığım dikkat edin echo. Dosyaları silmeye hazır olduğunuzda veya echo "$filename"ile değiştirdiğinizde değiştirin . Ayrıca, bunun istenen dizinde zaten edindiğinizde yapılması gerektiğini unutmayın .rm ./"$filename"rm -- "$filename"cd

(ab) awk kullanma

Awk güzel C benzeri bir dil olmak bize iki şekilde yardımcı olabilir: (1) for-loop ile dosya adları oluşturabilir ve bunları sprintfişlev yoluyla biçimlendirebiliriz ve (2) oluşturulan dosyaları system()bizim rmkomut dosyamızı ve komutumuzu geçirecek komutla silebiliriz kime /bin/sh:

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

Perl

Dosya adlarını "oluşturduğumuz" portatif yaklaşım fikrine devam ederek, Perl'de de aynısını yapabiliriz:

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'

0

Kadar basit

rm partialfilename* -f

Örneğinizde

rm a_00075* -f

1
Üzgünüm, ama bu bir aralık değil, bunların hepsi ile başlayan dosyalar a_00075...
Fabby

1
* bir joker karakterdir, OP bir ARALIK nasıl silineceğine dair bir cevap arıyor ... örneğin 1'den 100'e kadar dosyalarınız varsa ve # 41 ila # 75'i silmek istiyorsanız
Joshua Besneatte
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.