Bulmada exec ile noktalı virgül (;) vs artı (+) kullanma


159

Kullanım arasında çıkışta neden bir fark var?

find . -exec ls '{}' \+

ve

find . -exec ls '{}' \;

Bende var:

$ find . -exec ls  \{\} \+
./file1  ./file2

.:
file1  file2  testdir1

./testdir1:
testdir2

./testdir1/testdir2:


$ find . -exec ls  \{\} \;
file1  file2  testdir1
testdir2
./file2
./file1

Yanıtlar:


249

Bu en iyi şekilde bir örnekle gösterilebilir. Diyelim ki findbu dosyalar ortaya çıkıyor:

file1
file2
file3

-execNoktalı virgül ( find . -exec ls '{}' \;) ile kullanmak ,

ls file1
ls file2
ls file3

Ancak bunun yerine artı işareti ( find . -exec ls '{}' \+) kullanırsanız, olabildiğince çok dosya adı tek bir komuta bağımsız değişken olarak iletilir:

ls file1 file2 file3

Dosya adlarının sayısı yalnızca sistemin maksimum komut satırı uzunluğu ile sınırlıdır. Komut bu uzunluğu aşarsa, komut birden çok kez çağrılır.


1
Teşekkürler. sonuçta elde edilen dosyaları sıralamak için çok kullanışlıdır: find -maxdepth 1 -type f -mtime -1 -exec ls -ltr {} \ +
fbas

1
Aptal q: +ile ilişkili -execher zaman kaçtı, ancak ile +ilişkili -mtimeolmadığını fark ettim . Sebebini biliyor musun? Sanırım bununla ;ilişkili kaçmak alışkanlık -exec.
kevinarpe

3
@kevinarpe, bunu alışkanlık haline getirmek için tebeşirlendirirdim ;. Kaçmak için hiç gerek olmadığını hayal bile edemiyorum+
Martin

36

Şimdiye kadar olan tüm cevaplar doğrudur. Ben bunu echoyerine açıklanan davranışın (bana) daha açık bir gösteri olarak sunuyoruz ls:

Noktalı virgülle, komut echobulunan dosya başına (veya başka bir dosya sistemi nesnesi) bir kez çağrılır:

$ find . -name 'test*' -exec echo {} \;
./test.c
./test.cpp
./test.new
./test.php
./test.py
./test.sh

Bir artı ile, komut echosadece bir kez çağrılır. Bulunan her dosya bir argüman olarak aktarılır.

$ find . -name 'test*' -exec echo {} \+
./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh

Eğer findsonuçların çok sayıda yukarıya dönüşler, komut parametrelerinin sayısının belirlenmesi denilen jikleye olmak bulabilirsiniz.


1
Sonuçları yalnızca kabuğa geçirmeyi güvenli hale getiren bir sayıya eklenmemeli mi? En azından ne xargs... prensip olarak asla çok fazla argüman boğmaz.
Rmano

1
@Rmano: Solaris'te find(ve xargs) tüketilebileceğinden daha fazla argüman yaydığını gördüm . xargs(Ve findde) GNU findutils` daha makul davranmaya görünüyor, ama herkes GNU kullanır.
Johnsyweb

2
@Johnsyweb, tüm POSIX find, argüman sayısındaki sınıra ulaşmaktan kaçınmaya çalışır. Bu da Solaris'i içeriyor (en az 10 tane). Nerede başarısız olabilir gibi bir şey yaparsanız olduğunu find ... -exec ksh -c 'cmd "$@" "$@"' sh {} +veya find ... -exec ksh -c 'files="$*" cmd "$@"' sh {} +ama findgerçekten bunun için suçladı olamaz. GNU'nun finden son finddesteklenen uygulamalardan biri olduğuna dikkat edin +(GNU sistemlerine bağlantı noktası komut dosyası için bir acıydı).
Stephane Chazelas

19

Gönderen man find:

-exec komutu;

Komutu çalıştır; 0 durumu döndürülürse true. Bulmak için aşağıdaki tüm bağımsız değişkenler, ';' ile karşılaşıldı. '{}' Dizesi, bazı find sürümlerinde olduğu gibi, yalnızca yalnız olduğu bağımsız değişkenlerde değil, komutun bağımsız değişkenlerinde gerçekleştiği her yerde işlenen geçerli dosya adıyla değiştirilir. Bu yapıların her ikisinin de kabuğundan genişlemesini önlemek için kaçması ('\' ile) veya alıntılanması gerekebilir. '-Exec' seçeneğinin kullanımına ilişkin örnekler için ÖRNEK sn bölümüne bakın. Belirtilen komut her eşleşen dosya için bir kez çalıştırılır. Komut başlangıç ​​dizininde yürütülür. -Exec seçeneğinin kullanımını çevreleyen kaçınılmaz güvenlik sorunları vardır;

-exec komutu {} +

-Exec seçeneğinin bu değişkeni, seçilen dosyalarda belirtilen komutu çalıştırır, ancak komut satırı, seçilen her dosya adı sonuna eklenerek oluşturulur ; komutun toplam çağrı sayısı, eşleşen dosya sayısından çok daha az olacaktır. Komut satırı, xargs'ın komut satırlarını oluşturduğu gibi oluşturulur. Komutta yalnızca bir {{} örneğine izin verilir. Komut başlangıç ​​dizininde yürütülür.

Yani, Anladığım kadarıyla, \;bulduğu her dosya için ayrı bir komutu çalıştırır find, oysa \+dosyaları ekler ve hepsi tek bir komutu yürütür. \O yüzden, bir kaçış karakteridir:

ls testdir1; ls testdir2 

vs

ls testdir1 testdir2

Kabuğumda yukarıdakileri yapmak sorunuzun çıktısını yansıtıyordu.

ne zaman kullanmak istediğinize örnek \+

İki dosya varsayalım, 1.tmpve 2.tmp:

1.tmp:

1
2
3

2.tmp:

0
2
3

İle \;:

 find *.tmp -exec diff {} \;
> diff: missing operand after `1.tmp'
> diff: Try `diff --help' for more information.
> diff: missing operand after `2.tmp'
> diff: Try `diff --help' for more information.

Halbuki \+(sonuçlarını birleştirmek için find) kullanıyorsanız:

find *.tmp -exec diff {} \+
1c1,3
< 1
---
> 0
> 2
> 30

Yani bu durumda diff 1.tmp; diff 2.tmpvediff 1.tmp 2.tmp

\;Uygun ve \+gerekli olacak durumlar vardır . Kullanımı \+ile rmdosyaların performansı (hız) çok sayıda çıkarıyorsanız böyle bir örnek, daha üstün olacaktır \;.


Ben de adam sayfasını okuyabilirim. Ve yaptım, ama kullanma arasındaki farkı anladığımı sanmıyorum; vs +
Ankur Agarwal

Ben -1 adil olduğunu sanmıyorum, ben adam benim anlayış açıkladı. Sadece adamı kopyalayıp gitmedim. ancak yanıtımı daha iyi bir örnek içerecek şekilde düzenledim.
matchew

10

findözel sözdizimine sahiptir. Sen kullanmak {}oldukları gibi buldukları dosyanın yoluna ve (en) kabukları aksi şekilde yorumlayabilir yok olarak bulmak için anlam çünkü. Ters eğik çizgiye ihtiyacınız var, \;çünkü noktalı virgül kabuğa bir anlam katıyor, daha önce yiyebilen kabuk find. Yani findkabuk yapıldıktan SONRA, C programına aktarılan argüman listesinde görmek isteyenler

"-exec", "rm", "{}", ";"

ancak \;kabuktan bağımsız değişkenlere noktalı virgül almak için komut satırına ihtiyacınız vardır .

İle kurtulabilirsiniz \{\}çünkü kabuk alıntılı yorum \{\}sadece {}. Benzer şekilde, '{}' kullanabilirsiniz.

Ne edemez yapmak kullanımıdır

 -exec 'rm {} ;'

çünkü kabuk bunu tek bir argüman olarak yorumluyor ,

"-exec", "rm {};"

ve rm {} ;bir komutun adı değil. (En azından birisi gerçekten etrafta dolaşmadığı sürece.)

Güncelleme

aradaki fark

$ ls file1
$ ls file2

ve

$ ls file1 file2

+Komut satırında üzerine isimlerini catenating edilir.


1
Ne dediğini anlıyorum. Kullanmak arasındaki farkın ne olduğunu soruyorum; vs +
Ankur Agarwal

1
üzgünüm, ama sorumu veya yorumumu dikkatlice okudun mu? Belki de tekrar söylemem gerek. Bulmada exec ile noktalı virgül kullandığımda neden find ile exec ile birlikte kullandığımda neden farklı bir o / p var?
Ankur Agarwal

2
Bu, komutun NEDEN böyle olduğu, kabul edilen cevabın kapsamadığı için mükemmel bir açıklamadır. Teşekkürler!
Sherwin Yu

1

;(Noktalı virgül) veya +(artı işareti) arasındaki fark , bağımsız değişkenlerin find'ın -exec/ -execdirparametresine nasıl aktarıldıklarıdır . Örneğin:

  • kullanarak ;birden fazla komut yürütür (her bağımsız değişken için ayrı ayrı),

    Misal:

    $ find /etc/rc* -exec echo Arg: {} ';'
    Arg: /etc/rc.common
    Arg: /etc/rc.common~previous
    Arg: /etc/rc.local
    Arg: /etc/rc.netboot
    

    Aşağıdaki tüm argümanlar findkomuta argümanlar olarak alınır.

    Dize {}, işlenmekte olan geçerli dosya adıyla değiştirilir.

  • using +, mümkün olan en düşük komutları yürütür (argümanlar bir araya getirildiği için). xargsKomutun nasıl çalıştığına çok benzer , bu nedenle satır başına maksimum argüman sınırını aşmamak için komut başına mümkün olduğunca fazla argüman kullanır.

    Misal:

    $ find /etc/rc* -exec echo Arg: {} '+'
    Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot
    

    Komut satırı, seçilen her dosya adı sonuna eklenerek oluşturulur.

    {}Komut içinde yalnızca bir örneğine izin verilir.

Ayrıca bakınız:


-5

temizlik için dosya bulmaya çalışıyorduk.

bulmak. -exec echo {} \; komuta sonuçta gece boyunca koştu.

bulmak. -exec echo {} \ + sonuç aldı ve yalnızca birkaç saat sürdü.

Bu yardımcı olur umarım.


2
Bu cevap, bu iki yolun nasıl çalıştığını ve ürettikleri sonuçların nasıl farklı olduğunu açıklamaz.
misko321
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.