Unix: Bir dosyada listelenen dosyalar nasıl silinir?


92

Silmek istediğim dosya maskelerinin listesini içeren uzun bir metin dosyam var

Misal:

/tmp/aaa.jpg
/var/www1/*
/var/www/qwerty.php

Onları silmem gerekiyor. Rm "cat 1.txt" denendi ve listenin çok uzun olduğunu söylüyor.

Bu komutu buldum, ancak listeden klasörleri kontrol ettiğimde, bazılarının hala dosyaları var. xargs rm <1.txtManuel rm çağrısı, dosyaları bu tür klasörlerden kaldırır, bu nedenle izinlerle ilgili bir sorun yok.


8
Altı yıl sonra olsa bile: Cevaplardan birini kabul eder misiniz? Bu, soruyu çözüldü olarak işaretler ve diğer kullanıcılara da yardımcı olur.
MERose

Yanıtlar:


114

Bu çok verimli değildir, ancak glob kalıplarına ihtiyacınız varsa işe yarar (/ var / www / * 'da olduğu gibi)

for f in $(cat 1.txt) ; do 
  rm "$f"
done

Herhangi bir deseniniz yoksa ve dosyadaki yollarınızın beyaz boşluklar veya diğer garip şeyler içermediğinden eminseniz, xarg'leri şu şekilde kullanabilirsiniz:

xargs rm < 1.txt

4
Yol boşluk içeriyorsa ilk çözüme (CAT kullanarak) ne olacak?
a.dibacco

58

Dosya listesinin dosyada olduğunu varsayarsak, şunu yapın 1.txt:

xargs rm -r <1.txt

Bu -rseçenek, 'da adı verilen herhangi bir dizine yinelemeye neden olur 1.txt.

Herhangi bir dosya salt -fokunursa, silmeyi zorlamak için seçeneği kullanın:

xargs rm -rf <1.txt

Programlı silme yapan herhangi bir araca girdi verirken dikkatli olun . Make belli Girdi dosyasında adı dosyaları gerçekten silinecek olduğunu. Görünüşte basit yazım hataları konusunda özellikle dikkatli olun. Örneğin, bir dosya ile soneki arasına bir boşluk girerseniz, bu iki ayrı dosya adı olarak görünecektir:

file .txt

aslında iki ayrı dosyadır: fileve .txt.

Bu çok tehlikeli görünmeyebilir, ancak yazım hatası şöyle bir şeyse:

myoldfiles *

Yerine ile başlayan tüm dosyaları silme Ardından myoldfiles, silmeden bitireceğiz myoldfilesve tüm geçerli dizinde olmayan nokta dosyaları ve dizinleri. Muhtemelen istediğin şey değil.


1
"myoldfiles /" veya "/ tmp" -rf ile daha da feci. "/" Yanındaki boşluk karakterine dikkat edin.
Ray

23

Bunu kullan:

while IFS= read -r file ; do rm -- "$file" ; done < delete.list

Glob genişletmeye ihtiyacınız varsa, alıntı yapmayı ihmal edebilirsiniz $file:

IFS=""
while read -r file ; do rm -- $file ; done < delete.list

Ancak, dosya adlarının "sorunlu" içerik içerebileceği ve alıntılanmamış sürümü kullanacağım konusunda uyarılalım. Bu kalıbı dosyada hayal edin

*
*/*
*/*/*

Bu, mevcut dizinden oldukça fazla şeyi siler! Silme listesini artık glob kalıplarına gerek kalmayacak şekilde hazırlamanızı ve ardından ilk örneğimdeki gibi alıntı yapmanızı tavsiye ederim .


3
Bu, şu anda tek cevap olduğunu kolları tüm /My Dir With Spaces/ /Spaces and globs/*.txt, --file-with-leading-dashesve GNU / Linux, MacOS ve BSD'de POSIX ve eserlerini olan bir bonus olarak.
diğer adam

17

Yeni satır karakterini sınırlayıcı olarak tanımlamak için '\ n' kullanabilirsiniz.

xargs -d '\n' rm < 1.txt

-Rf'ye dikkat edin çünkü 1.txt boşluklu yollar içeriyorsa istemediklerinizi silebilir. Bu nedenle yeni satır sınırlayıcı biraz daha güvenli.

BSD sistemlerinde, yeni satır karakterlerini şu şekilde sınırlayıcı olarak kullanmak için -0 seçeneğini kullanabilirsiniz:

xargs -0 rm < 1.txt

1
OS X'te bu beni alırxargs: illegal option -- d
waldyrious

İyi bir nokta. Görünüşe göre -0OS X'dekinden başka bir seçenek yok .
Ray

2
xargs -I_ rm _OS X'de de çalışır :) bkz. stackoverflow.com/a/39335402/266309
waldyrious

BSD xargs kullanıyorsanız (yok ise -d), önce satırsonlarını boş karakterlere dönüştürebilirsiniz:tr '\n' '\0' < 1.txt | xargs -0 rm
OrangeDog

14

Bu tek astarı kullanabilirsiniz:

cat 1.txt | xargs echo rm | sh

Kabuk genişletme yapar ancak rmminimum sayıda çalıştırır .


Herhangi bir genişleme çok uzun olmadığı sürece?
Douglas Leeder

1
Doğru, bir glob çok uzun bir argüman listesi oluşturabilir - her rm'ye aktarılan argüman sayısını azaltmak için -n <n>argüman ekleyebilirsiniz xargs, ancak bu yine de sizi sınırı aşan tek bir glob'dan korumaz.
tgdavies

13

xargs -I{} sh -c 'rm {}' < 1.txtne istersen yapmalısın. Bu komuta dikkat edin, çünkü o dosyadaki tek bir yanlış giriş çok fazla soruna neden olabilir.

Bu cevap, @tdavies orijinalin kabuk genişletmesi yapmadığını belirttikten sonra düzenlendi.


Teşekkürler, ancak klasörleri silmeye gerek yok, sadece dosyalar
Alexander

2
Kabuk tarafından asla 'görülmediklerinden' küreler genişlemeyecek.
tgdavies

@tdavies vay - haklısın. Bu komut (biraz daha çirkin de olsa) çalışacaktır:xargs -I{} sh -c 'rm {}' < 1.txt
Mark Drago

4

Bu özel durumda, diğer cevaplarda belirtilen tehlikelerden dolayı,

  1. Örneğin, Vim ve :%s/\s/\\\0/gboşluk karakterlerinden ters eğik çizgi ile kaçarak düzenleyin.

  2. Ardından :%s/^/rm -rf /, komutu başına ekleyin. İle -rsize dosyaları burada yer alan sonra listelenen dizinleri olması endişe gerekmez ve birlikte -fbuna bağlı eksik dosyalar veya yinelenen girdileri şikayet olmaz.

  3. Tüm komutları çalıştırın: $ source 1.txt


Boşluklar, kaçması gereken tek karakter değildir, dosya adlarında popüler olan, ayrıca istenmeyen genişlemeye yol açabilecek her türden parantezdir.
emk2203

4

cat 1.txt | xargs rm -f | bash Komutu çalıştırmak yalnızca dosyalar için aşağıdakileri yapacaktır.

cat 1.txt | xargs rm -rf | bash Komutu çalıştırmak aşağıdaki özyinelemeli davranışı yapacaktır.


2

Sadece başka bir yol sağlamak için aşağıdaki komutu da kullanabilirsiniz.

$ cat to_remove
/tmp/file1
/tmp/file2
/tmp/file3
$ rm $( cat to_remove )

1

İşte başka bir döngü örneği. Bu ayrıca, girişin bir 'dosya' (veya bir 'dizin') olup olmadığını kontrol etmeye örnek olarak bir 'if-ifadesi' içerir:

for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done

0

Burada gelen klasörler kümesi kullanabilirsiniz deletelist.txt ederken bazı desenleri kaçınarak yanı

foreach f (cat deletelist.txt)
    rm -rf ls | egrep -v "needthisfile|*.cpp|*.h"
end

0

Bu, dosya adlarının boşluklara sahip olmasına izin verecektir (yeniden üretilebilir örnek).

# Select files of interest, here, only text files for ex.
find -type f -exec file {} \; > findresult.txt
grep ": ASCII text$" findresult.txt > textfiles.txt
# leave only the path to the file removing suffix and prefix
sed -i -e 's/:.*$//' textfiles.txt
sed -i -e 's/\.\///' textfiles.txt

#write a script that deletes the files in textfiles.txt
IFS_backup=$IFS
IFS=$(echo "\n\b")
for f in $(cat textfiles.txt); 
do 
rm "$f"; 
done
IFS=$IFS_backup

# save script as "some.sh" and run: sh some.sh

0

Birinin joker karakter genişletmesi olmadan tercih etmesi sedve kaldırması durumunda :

sed -e "s/^\(.*\)$/rm -f -- \'\1\'/" deletelist.txt | /bin/sh

Hatırlatma: Dosyada mutlak yol adları kullanın veya doğru dizinde olduğunuzdan emin olun.

Ve tamlık için şununla aynı awk:

awk '{printf "rm -f -- '\''%s'\''\n",$1}' deletelist.txt | /bin/sh

Tek tırnaklar kaldırılırsa joker karakter genişletme çalışacaktır, ancak dosya adının boşluk içermesi durumunda bu tehlikelidir. Bu, joker karakterlerin etrafına tırnak işaretleri eklemelidir.

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.