Çoklu dizinleri find -prune seçeneğine aktarma


9

findYedek dosyaları bulmak ve silmek için kullanıyorum , ancak aramadan belirli dizinleri hariç tutmak istiyorum. Yedek dosya adları son bulabilir .bck, bak, ~, veya backup.

Hariç tutulacak yalnızca üç dizin içeren Minimum Çalışma Örneği (MWE) kodu:

#! /bin/bash
find . -type d \( -path "./.*" -o -path "./Music" -o -path "./Documents" \) -prune -o -type f \( -name "*.bck" -o -name "*.bak" -o -name "*~" -o -name "*.backup" \) -print0 | xargs -0 --no-run-if-empty trash-put

Sözdizimi \( -path "dir1" -o -path "dir2" ... -o -path "dirN" \) -prunebiraz aksak görünüyor, özellikle de hariç tutulacak yaklaşık on dizin varsa, ancak MWE'de sadece üç tane göstermiştim.

Hariç tutulan dizinlerin listesi olan bir girdi dosyasını veya hizmete basılabilen dizi veya liste benzeri bir yapıyı kullanmanın daha zarif bir yolu var mı?

Orijinal sorumu yazarken daha açık olmadığım için üzgünüm.

Not: trash-putdosyaları Trashcansilmek yerine taşımak için kullanılan bir yardımcı programdır [1].

[1]. https://github.com/andreafrancia/trash-cli

Yanıtlar:


4

Bildiğim kadarıyla find, bir dosyadan kalıp okumayı söyleme seçeneği yoktur . Kolay bir çözüm, hariç tutmak istediğim kalıpları bir dosyaya kaydetmek ve bu dosyayı tersine çevirmek grep. Örnek olarak, aşağıdaki dosyaları ve dizinleri oluşturdum:

$ tree -a
.
├── a
├── .aa
├── .aa.bak
├── a.bck
├── b
├── .dir1
│   └── bb1.bak
├── dir2
│   └── bb2.bak
├── b.bak
├── c
├── c~
├── Documents
│   └── Documents.bak
├── exclude.txt
├── foo.backup
└── Music
    └── Music.bak

Ben doğru yayınlanmıştır örnek anlasalardı, taşımak istediğiniz a.bck, .aa.bak, b.bak, c~, foo.backupve dir2/bb2.bakçöp ve izni .aa.bak, .dir1/bb1.bak, Documents/Documents.bakve Music/Music.bakneredeler. Bu nedenle, dosyayı exclude.txtaşağıdaki içeriklerle oluşturdum (istediğiniz kadar ekleyebilirsiniz):

$ cat exclude.txt 
./.*/
./Music
./Documents

Ben ./.*/orijinal bulmayı anladım çünkü .foogeçerli dizinde gizli yedekleme dosyaları ( ) taşımak ama gizli dizinlerde ( .foo/bar) herhangi bir yedek dosyaları hariç tutmak istediğiniz anlamına gelir . Yani, şimdi findkomutu çalıştırabilir ve grepistenmeyen dosyaları hariç tutmak için kullanabilirsiniz :

$ find . -type f | grep -vZf exclude.txt | xargs -0 --no-run-if-empty trash-put

Grep seçenekleri:

   -v, --invert-match
          Invert  the  sense  of matching, to select non-matching
          lines.  (-v is specified by POSIX.)
   -f FILE, --file=FILE
          Obtain patterns from FILE, one  per  line.   The  empty
          file  contains  zero  patterns,  and  therefore matches
          nothing.  (-f is specified by POSIX.)
   -Z, --null
          Output a zero byte (the ASCII NUL character) instead of
          the  character  that normally follows a file name.  For
          example, grep -lZ outputs a zero byte after  each  file
          name  instead  of the usual newline.  This option makes
          the output unambiguous, even in the  presence  of  file
          names  containing  unusual  characters  like  newlines.
          This  option  can  be  used  with  commands  like  find
          -print0,  perl  -0,  sort  -z,  and xargs -0 to process
          arbitrary file names, even those that  contain  newline
          characters.

Açık olmadığım için çok üzgünüm. Lütfen umarım gözden geçirilmiş soru daha açıktır.
chandra

@chandra güncellenmiş yanıtı, aynı genel fikri, farklı ayrıntıları görün.
terdon

Teşekkür ederim. Sorumu amacım için çok açık ve mükemmel bir şekilde cevapladınız. Cevabınızı kabul ettim.
chandra

6

GNU find ile (örneğin, gömülü olmayan Linux veya Cygwin altında), -regex tüm bu -pathjoker karakterleri tek bir normal ifade içinde birleştirmek .

find . -regextype posix-extended \
     -type d -regex '\./(\..*|Music|Documents)' -prune -o \
     -type f -regex '.*(\.(bck|bak|backup)|~)' -print0 |
xargs -0 --no-run-if-empty trash-put

FreeBSD veya OSX ile, -Eyerine kullanın -regextype posix-extended.


Mükemmel bir alternatif cevap için teşekkür ederim. İki cevabı kabul edememek utanç verici.
chandra

3

Grup -path ... -prunebir ifadeye göre kapalı \( ... \)kullanılarak -o( veya ) mantık.

find /somepath \( -path /a -prune -o \
                  -path /b -prune -o \
                  -path /c -prune \
               \) \
               -o -print

Örnek şuna yinelerler değil dizinleri veya veya altındaki dosyalar /somepath/a, /somepath/bve /somepath/c.

Birden fazla eylem kullanan daha spesifik bir örnek.

find / \( -path /dev -prune -o \
          -path /proc -prune -o \
          -path /sys -prune \
       \) \
       -o -printf '%p ' -exec cksum {} \;

1

Bu bir sorudan çok kabuklu bir soru gibi görünüyor find. ( -name dir1 -o -name dir2 ) -prune("\" Yok!) İçeren bir dosya ile bunu yapabilirsiniz:

find ... $(< /path/to/file)

Bulma çağrısını değiştirmeden ( eval find değiştirmeden ($ IFS'ye veya $ IFS'yi değiştirerek), yalnızca boşluksuz yollarla çalışır.

Dosyayı daha basit tutmak istiyorsanız bir komut dosyası yazabilirsiniz.

# file content
dir1
dir2
dir3

# script content
#!/bin/bash
file=/path/to/file
# file may be checked for whitespace here
grep '[^[:space:]]' "$file" | { empty=yes
  while read dir; do
    if [ yes = "$empty" ]; then
      echo -n "( "
      empty=no
    else
      echo -n " -o "
    fi
    echo -n "-name ${dir}"
  done
  if [ no = "$empty" ]; then
    echo -n " ) -prune"
  fi; }

Ve kullan

find ... $(/path/to/script)

yerine.


Açık olmadığım için çok üzgünüm. Lütfen umarım gözden geçirilmiş soru daha açıktır.
chandra

@chandra Ben senin soru nettir nasıl ne de ben (önemsiz replecement haricinde benim çözüm ile ilgili bir sorun ne olabilir anlıyorsunuz -nametarafından path).
Hauke ​​Laging

Yukarıdaki senaryom çalışıyor ve istediğim şeyi yapıyor. Sadece \( -path "dir1" -o -path "dir2" ... -o -path "dirN" \) -prunebelirli dizinleri özyinelemeli aramadan hariç tutmaktan daha güzel bir yol olup olmadığını bilmek istedim find. Dosyaların içinde hiçbir şey aramıyorum, belirli dosyaları siliyorum ve arama yolumdaki belirli dizinlerden kaçınıyorum. Senaryonuzun da ne yapmaya çalıştığını anlamıyorum. Görünüşe göre bir iletişimsizlik var. Afedersiniz. Bırakalım onu ​​bırakalım.
chandra
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.