Nokta dosyalarına genişleyen ancak `..` ye değil kabuk dosya adı deseni?


13

Son zamanlarda beklenmedik bir şekilde genişleyen bir kabuk paterninden kaynaklanan küçük bir aksilik yaşadım. /rootDizindeki bir dizi nokta dosyasının sahibini değiştirmek istedim , bu yüzden yaptım

chown -R root .*

Doğal olarak, .*genişleyen ..bir felaket oldu.

bashBu davranış bazı kabuk seçeneği tweaking ile değiştirilebileceğini biliyorum , ama varsayılan ayarlarla dizindeki her nokta dosyasına genişletmek ama değil .ve herhangi bir desen var ..mı?

Yanıtlar:


20

Bash, ksh ve zsh daha iyi çözümlere sahiptir, ancak bu cevapta bir POSIX kabuğu varsayıyorum.

Desen .[!.]*, nokta ile başlayan ve ardından nokta olmayan bir karakterle başlayan tüm dosyalarla eşleşir. ( [^.]Bazı kabuklar tarafından desteklenmesine rağmen hepsinin desteklemediğine dikkat edin , joker karakter desenlerindeki karakter kümesi için taşınabilir sözdizimi [!.].) Bu nedenle .ve ..iki nokta ile başlayan dosyaları hariç tutar . Desen ..?*, iki nokta ile başlayan ve sadece olmayan dosyaları işler ...

chown -R root .[!.]* ..?*

Bu, tüm dosyalarla eşleşecek klasik desendir:

* .[!.]* ..?*

Bu yaklaşımın bir sınırlaması, kalıplardan biri hiçbir şeyle eşleşmezse, komuta aktarılmasıdır. Bir komut dosyasında, bir dizindeki tüm dosyaları eşleştirmek istediğinizde .ve ..hepsinin hantal olduğu birkaç çözüm vardır:

  • * .*Tüm girdileri numaralandırmak .ve ..bir döngüde hariç tutmak için kullanın . Desenlerden biri veya her ikisi de hiçbir şeyle eşleşmeyebilir, bu nedenle döngü her dosyanın varlığını kontrol etmelidir. Diğer kriterlere göre filtreleme şansınız var; örneğin, -hsarkan sembolik bağlantıları atlamak istiyorsanız testi kaldırın .

    for x in * .*; do
      case $x in .|..) continue;; esac
      [ -e "$x" ] || [ -h "$x" ] || continue
      somecommand "$x"
    done
  • Komutun yalnızca bir kez çalıştırıldığı daha karmaşık bir varyant. Konumsal parametrelerin hızlandığını unutmayın (POSIX mermilerinin dizileri yoktur); bu bir sorunsa bunu ayrı bir işleve koyun.

    set --
    for x in * .[!.]* ..?*; do
      case $x in .|..) continue;; esac
      [ -e "$x" ] || [ -h "$x" ] || continue
      set -- "$@" "$x"
    done
    somecommand "$@"
  • * .[!.]* ..?*Triptik kullanın . Yine, bir veya daha fazla desen hiçbir şeyle eşleşmeyebilir, bu nedenle mevcut dosyaları kontrol etmemiz gerekir (sarkan sembolik bağlantılar dahil).

    for x in * .[!.]* ..?*; do
      [ -e "$x" ] || [ -h "$x" ] || continue
      somecommand "$x"
    done
  • * .[!.]* ..?*Tryptich kullanın ve komutu her kalıp için bir kez, ancak yalnızca bir şeyle eşleştiğinde çalıştırın. Bu, komutu yalnızca bir kez çalıştırır. Konumsal parametrelerin hızlandığını unutmayın (POSIX kabuklarında diziler yoktur), bu bir sorunsa bunu ayrı bir işleve yerleştirin.

    set -- *
    [ -e "$1" ] || [ -h "$1" ] || shift
    set -- .[!.]* "$@"
    [ -e "$1" ] || [ -h "$1" ] || shift
    set -- ..?* "$@"
    [ -e "$1" ] || [ -h "$1" ] || shift
    somecommand "$@"
  • Kullanın find. GNU veya BSD bulması ile, -mindepthve ile özyinelemeden kaçınmak kolaydır -maxdepth. POSIX bulmayla, biraz daha karmaşıktır, ancak yapılabilir. Bu form, komutun dosya başına bir kez yerine tek bir kez çalıştırılmasına izin verme avantajına sahiptir (ancak bu garanti edilmez: sonuçta ortaya çıkan komut çok uzunsa, komut birkaç toplu olarak çalıştırılır).

    find . -name . -o -exec somecommand {} + -o -type d -prune

6

Dosya adlarının tümü en az üç karakter içeriyorsa (nokta dahil) çalışır:

chown -R root .??*

Daha sağlam bir çözüm için şunları kullanabilirsiniz find:

find . -maxdepth 1 -name '.*' -exec chown -R root {} \;
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.