rsync regex kullanarak yalnızca bazı dosyaları içerir


11

Onların dosya adı desen, büyük / küçük harf duyarsız dayalı bir yolda özyinelemeli bazı dosyaları kopyalamak için rsync çalıştırmak çalışıyorum . Bu rsync çalıştırmak için yaptım:

$ rsync -avvz --include ='*/' --include='.*[Nn][Aa][Mm][E].*' --exclude='*' ./a/ ./b/

Hiçbir şey kopyalanmaz, hata ayıklama çıktısı şunu gösterir:

[sender] hiding file 1Name.txt because of pattern *
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] hiding directory test1 because of pattern *
[sender] hiding file NaMe.txt because of pattern *

Kullanmayı denedim: --include='*[Nn][Aa][Mm][E]*'ve diğer kombinasyonlar ama yine de gitmiyor.

Bazı dosyaları dahil etmek için regex nasıl kullanılır hakkında herhangi bir fikir?


4
Neden kullanıyorsunuz --exclude='*'?

2
bu yüzden içerme işleminin parçası olmayan her şeyi hariç tutar.

'desen nedeniyle 1Name.txt dosyasını gizlemek ' şu anlama gelir: - "Bu --exclude kuralının komutta olması gerekiyor mu?" veya Bazı dosyaları hariç tutmak istiyorsanız neden " ".
Akshay Patil

Yanıtlar:


5

rsync normal ifade etmiyor. Biraz gizemli olsa da, bul ve grep yazabilirsiniz. Hedef dosyaları bulmak için:

find a/ |
grep -i 'name'

Ama hepsine "a /" öneki eklenmiş - bu da mantıklı, ancak sonuç olarak rsync için kabul edilebilir bir örüntü listesi var ve "a /" öneki rsync I için çalışmaz. keserek kaldıracağım:

find . |
grep -i 'name' |
cut -d / -f 2-

Hala bir sorun var - alt dizinlerdeki dosyaları hala özleyeceğiz, çünkü rsync dışlama listesinde dizinleri aramıyor. Ben dahil desenleri listesine eşleşen herhangi bir dosyanın alt dizinleri eklemek için awk kullanacağım:

find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}'

Geriye kalan tek şey listeyi rsync'e göndermek - standart girdide rsync'e desen listesi sağlamak için --include-from = - değişkenini kullanabiliriz. Yani, hep birlikte:

find a/ |
grep -i 'name' |
cut -d / -f 2- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

'A' kaynak dizinine "a /" ve "./a/" olmak üzere iki farklı yoldan bahsedildiğini unutmayın. Bu ince ama önemlidir. İşleri daha tutarlı hale getirmek için son bir değişiklik yapacağım ve her zaman kaynak dizini "./a/" olarak adlandıracağım. Ancak bu, find komutunun sonucunun ön yüzünde fazladan bir "./" olacağı için cut komutunun değişmesi gerektiği anlamına gelir:

find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) {sub("/[^/]*$", ""); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

Çalıştırmayı denedi, cut komutuyla ilgili sorunlar yaşadı. Bu -tgeçerli bir anahtar gibi görünüyor .

edit: demek -t geçerli bir anahtar değil

üzgünüm, -d olmalı. sed kullanmaya başladım ve sonra daha net olduğunu düşündüğüm için kesmek için değiştim, ancak komutlarımı düzenlemeyi unuttum: S

İzleyin: Dosya adını + uzantıların karışımını eşleştirdiğim için argümanları almak için komut dosyasını düzenlemeye çalıştım ($ 1 = path_to_search, egrep için desen olarak 2 $). Bu parçalar iyi çalışıyor, ancak beklenen listeyi aldım, ancak rsync kopyalayamıyor. Örnekte olduğu gibi sadece tek isim karakter dizini ile çalışmak gibi görünüyor (a) tahminim cut komutunun, ana / veya kaynak dizinini temel alan karakterleri kesmek için değiştirilmesi mi gerekiyor? Bunu nasıl yapacağımı biraz kaybetti:
user1957413

Ah evet, oldukça haklısın. Herhangi bir uzunlukta bir dizin adı üzerinde çalışmalıdır, ancak geçerli dizinin dışındaki bir dizine başvurduğunuzda başarısız olur (çünkü önek bölümünde farklı sayıda eğik çizgi olacaktır). Bunu düzeltmek için, kes yerine sed kullanmanın en kolay yolu, örneğin: sed "s#^$1/*##" # içeren yollarda kesilecek buuuut. Bunu düzeltmek için gelen dizin adını alıntılamak zorundayız : prefix=$(echo "$1" | sed 's#/#\\/#g')ve sonra sed "s/^$prefix\\/*//"bash tırnak altlıkları bir kabus biraz;)
sqweek

7

Ben rsync filtre seçeneğini kullanmanızı öneririm. Örneğiniz için şunu yazın:

rsync -vam -f'+ *[Nn][Aa][Mm][E]*' -f'+ */' -f'- *' a b

ilk filtre kuralı rsync'e hangi kalıpları dahil edeceğini söyler. İkinci kurala rsync'e geçişindeki tüm dizinleri incelemesini bildirmek gerekir. Boş kirlerin dahil edilmesini önlemek için, -mseçenek tarafından açıkça hariç tutulurlar . Son filtre kuralı rsync'e şu ana kadar eşleşmeyen kalan tüm desenleri atmasını söyler.


Tatlı. Bu da işe yaradı. Ben kaynak ve hedef olarak a / b / kullanarak sabit b klasörü içinde alıyordu. Teşekkürler!
user1957413

Belirli bir ada sahip tüm dizinlerin içeriğini dahil etmek için -f '+ * [Nn] [Aa] [Mm] [E] **' (sonunda iki yıldız) kullanın.
fobik

2

ZSH kullanırsanız, büyük / küçük harf duyarlılığını kapatmak için (#i) bayrağını kullanabilirsiniz. Misal:

$ touch NAME
$ ls (#i)*name*
NAME

ZSH, normal yol gibi belirtilen hariç tutmaları da destekler, ancak bir başlangıç ​​~

$ touch aa ab ac
$ ls *~*c
aa ab

İstisnaları zincirleyebilirsiniz:

$ ls *~*c~*b
aa

Son olarak ne tür bir dosya döndürülmesini istediğinizi belirtebilirsiniz (dizin, dosya vb.). Bu, dizin için (/) ve dosya için (.) İle yapılır.

$ touch file
$ mkdir dir
$ ls *(.)
file

Tüm bunlara dayanarak, bu komutu şöyle yaparım:

rsync -avvz *(/) (#i)*name* ./a/ ./b/

(Bu seçicilerin hariç tutulmasına ihtiyaç duymuyorum)


1

@ sqweek 's yukarıdaki cevap harika, ama o awkbana örneğin verir gibi üst dizinleri oluşturmak için onun komut dosyası bir hata var şüpheli :

$ echo a/b/c/d | awk -F/ '{print; while(/\//) {sub("/[^/]*", ""); print}}'
a/b/c/d
a/c/d
a/d
a

Bunun gensubyerine kullanarak düzeltmek mümkün :

$ echo a/b/c/d | awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}'
a/b/c/d
a/b/c
a/b
a

Yani, awkbiraz değiştiğinde tam çözümü şöyle olurdu:

find ./a/ |
grep -i 'name' |
cut -d / -f 3- |
awk -F/ '{print; while(/\//) { $0=gensub("(.*)/[^/]*", "\\1", "g"); print}}' |
rsync -avvz --include-from=- --exclude='*' ./a/ ./b/

Teşekkürler. Cevabımı, regex'i satır sonuna ( sub("/[^/]*$")) sabitlemenin eşdeğer düzeltmesi ile düzenledi .
sqweek

0

En çok deneyime sahip olduğum dil olduğundan bir C # komut dosyası ile denedim. Eklemek istediğim dosyaların listesini oluşturabiliyorum, ancak birisi rsync hala bana bir yürüyüş yapmamı söylüyor. Klasörleri oluşturur, ancak dosyaları yok sayar. İşte elimde ne var ..

İlk önce dizinin içeriği:

~/mono$ ls -l
total 24
drwxr-xr-x 5 me me 4096 Jan 15 00:36 a
drwxr-xr-x 2 me me 4096 Jan 15 00:36 b
drwxr-xr-x 3 me me 4096 Jan 14 00:31 bin
-rw-r--r-- 1 me me 3566 Jan 15 00:31 test.cs
-rwxr-xr-x 1 me me 4096 Jan 15 00:31 test.exe
-rwxr--r-- 1 me me  114 Jan 14 22:40 test.sh

Sonra C # betiğinin çıktısı:

~/mono$ mono test.exe

/a/myfile/myfileseries.pdf
/a/myfile2/testfile.pdf

Ve hata ayıklama çıktısı:

~/mono$ mono test.exe | rsync -avvvz --include='*/' --include-from=- --exclude='*' ./a/ ./b/
[client] add_rule(+ */)
[client] parse_filter_file(-,20,3)
[client] add_rule(+ /a/myfile/myfileseries.pdf)
[client] add_rule(+ /a/myfile2/testfile.pdf)
[client] add_rule(- *)
sending incremental file list
[sender] make_file(.,*,0)
[sender] hiding file 1Name.txt because of pattern *
[sender] showing directory myfile2 because of pattern */
[sender] make_file(myfile2,*,2)
[sender] hiding file 1.txt because of pattern *
[sender] hiding file 2.txt because of pattern *
[sender] hiding file Name1.txt because of pattern *
[sender] showing directory test1 because of pattern */
[sender] make_file(test1,*,2)
[sender] hiding file NaMe.txt because of pattern *
[sender] showing directory myfile because of pattern */
[sender] make_file(myfile,*,2)
send_file_list done
send_files starting
[sender] hiding file myfile/myfileseries.pdf because of pattern *
[sender] hiding file myfile2/testfile.pdf because of pattern *
[sender] hiding file test1/test.txt because of pattern *

0

[EDIT] Bu yalnızca yerel olarak çalışır. Uzak yollar için, önce dizin yapısının oluşturulması gerekir.

Kabul edilen cevaptan daha basit; Üst dizinleri otomatik olarak içeren --file-from komutunu kullanın ve% P ile dosya yolunu yazdırın

find /tmp/source -wholename '*[Nn][Aa][Mm][E]*' -printf '%P\n' | rsync -vzrm --exclude='*/' --files-from=- /tmp/source/ /tmp/target/

Yalnızca kullanmak zorunda Yani findve rsync.

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.