Komut satırında * dışında bırak


14

A'nın kullanımının *neredeyse kaçınılmaz olduğu birçok durum vardır - örneğin rm -rf *binlerce alt klasör ve dosya içeren bir klasörde.

Ancak, yalnızca bir veya iki dosya veya klasörü rmkomutun dışında bırakmak isterseniz ne olur ? Yolumu araştırdım ve buradafind . -depth -not \( -name 'one' -o -name 'two' \ -o -name 'three' \) -exec rm {} \; belirtildiği gibi oldukça karmaşık çözümler buldum .

Bunu daha kolay bir şekilde yapma imkanı var mı - bu sapma olmadan find? Örneğin rm -rf --exclude='one' --exclude='two' --exclude='three' *rsync gibi rm -rf -e 'one','two','three' *mi yoksa sadece ?

Hatta belki bir genel olasılık şeyleri dışlamak için *(böylece diğer komutlar gibi cp, mv... kendi uygulamak zorunda değilsiniz)? Gibi bir şey *{'one','two','three'}mi?


3
Yalnızca bir veya iki dosyayı saklamak istiyorsanız, en basit ve en kolay yol bu dosyaları başka bir konuma taşımak, kalan tüm dosyaları silmek ve sakladığınız dosyaları taşımaktır. Çok daha fazla dosya tutmak istiyorsanız seçeneği findile kullanmak istiyorum --delete( rmher dosya için yürütmek gerek yok . Bu gereksiz yükü).
Hennes

Bu bir olasılık olurdu, ancak bahsettiğim kadar ayrıntılı. Komutları benzer bir şeyle birleştirebileceğimi biliyorum mv -t /tmp one two three && rm -rf * && mv -t . /tmp/one /tmp/two /tmp/three, ama bir şeyi açıkça dışlama imkanı veren bir çözümü tercih ederim *. Kesinlikle dosyaları taşımak veya başka bir hedefe kopyalamak bir seçenek olmayacaktır durumlar olacaktır.
David

2
İşte bu yüzden cevap olarak göndermedim. Sadece bir şeyler yapmanın daha az karmaşık bir yolu olarak (üç çok basit komut bir veya daha karmaşık olanlara karşı) RM ile birlikte karmaşıklıktan nefret ediyorum.
Hennes

Yanıtlar:


33

Bash İçin denilen bir kabuk seçeneği yoktur extglobedilir varsayılan olarak devre dışı standart kabuk sözdizimi ile uyumluluğu korumak için.Extglob verilenlere benzer operatörler tarafından sözdizimi tamamlar !(), ?(), @()biraz daha ve.

Açmak için extglobyazın shopt -s extglob. Geçerli kullanıcı türü için açık tutmak için echo 'shopt -s extglob' >> ~/.bashrc.

Rm Örneğin: ile extglobkullanabilirsiniz

rm -rf !(one|two|three)

İyi bir çözüm gibi görünüyor, ama aynı zamanda tarif edilen gibi bir duruma geldiğimde bunu açmak ve kapatmak istemiyorum.
David

3
@David: shoptşeyleri içine koyabilirsin, ~/.bashrcacıtmaz.
enzotib

Doğru yaparsam, extglob seçeneği etkisini değiştirmez, *bunun yerine !ek işlevlere sahip benzer göstergeler (gibi ) ekler ? Bu durumda güzel bir çözüm olurdu.
David

1
@David: Kesinlikle.
choroba

1
@David Standart kabuk sözdizimi ile uyumluluğu korumak için . Davranışın değişebileceği başka durumlar da olabilir.
gerrit

4

Ben tam olarak bunun dışında inşa ettik (henüz belge ekleyemedi sry).

Aşağıdaki gibi bir klasörünüz var:

$ ls
a b c d

Yazmak except b dsize avec

$ except b d
ac

Şimdi bunu borulayabilirsiniz rm.

except b d | xargs -0 rm

Bunu hatırlamak zor olabilir, bu yüzden neden sadece dışında bir komut dosyası oluşturmuyorsunuz rm-except:

#!/usr/bin/env bash

except "$@" | xargs -0 rm

Benzer şekilde kolay ls-except:

#!/usr/bin/env bash

except "$@" | xargs -0 ls

3
Bu güzel, ama extglob hakkında bildiğinizde gerçekten gerekli değil - askubuntu.com/a/329233/138369
David

1

Extglob'a bir alternatif olarak (bu çok iyi bir cevap olsa da ve herkesin shopt -s extglob globstar.bashrc'sinde olması gerekir ), $ GLOBIGNORE global değişkenini kullanabilirsiniz . Diyelim ki 'foo.txt' ve 'bar baz.txt' hariç her dosyayı almak istiyorsunuz:

GLOBIGNORE=foo.txt:'bar baz.txt'

... ancak bu kabuk seçeneğini açar dotglob, yani *bir nokta ile başlayan (normalde gizli olan) dosyalarla eşleşir. Yani aslında iki komuta ihtiyacınız var:

GLOBIGNORE=foo.txt:'bar baz.txt'
shopt -u dotglob

Bu global bir değişken olduğu için, $ GLOBSTAR oturumdan çıkarak veya

GLOBIGNORE=

Ayrıca yalnızca değişkene iletilen değişmez dizgiler üzerinde de çalışır. Ne demek istediğimi $ GLOBIGNORE ayarlayarak ve bu komutlar arasındaki farka bakarak görebilirsiniz:

printf '%s\n' *
printf '%s\n' ./*
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.