Neden kabuk otomatik olarak “işe yaramaz kedi kullanımı” nı düzeltmiyor? [kapalı]


28

Birçok insan satır boyunca kod içeren oneliner ve scriptler kullanır

cat "$MYFILE" | command1 | command2 > "$OUTPUT"

Birincisine catgenellikle "işe yaramaz kedi kullanımı" denir, çünkü teknik olarak, /usr/bin/cateğer komut olsaydı, bundan kaçınılması gereken yeni bir işlem başlatmayı gerektirir.

< "$MYFILE" command1 | command2 > "$OUTPUT"

Çünkü o zaman kabuk sadece başlaması command1ve stdinverilen dosyayı göstermesi yeterlidir .

Kabuk neden bu dönüşümü otomatik olarak yapmıyor? "Kedinin işe yaramaz kullanımı" sözdiziminin okunmasının daha kolay olduğunu ve kabukların otomatik olarak işe yaramaz kediden kurtulmak için yeterli bilgiye sahip olması gerektiğini düşünüyorum. catKabuk yolunda bir ikili kullanmanın içten yerine uygulamaya izin verilmelidir böylece POSIX standardında tanımlanmıştır. Kabuk, yalnızca tam bir argüman sürümü için uygulama içerebilir ve yoldaki ikili dosyaya geri dönebilir.


22
Bu komutlar aslında eşdeğer değildir, çünkü bir durumda stdin bir dosyadır ve diğerinde bu bir pipo, bu yüzden kesinlikle güvenli bir dönüşüm olmazdı. Yine de bunu yapan bir sistem yapabilirsin.
Michael Homer

14
Bir kullanım durumu hayal edemezsiniz, bir uygulamanın gereksiz yere davranışa dayanmadığı anlamına gelmez. Bir hata alma lseekvb hala davranışı tanımlanır ve farklı sonuçlar verebilir, farklı engelleme davranışı semantik olarak anlamlı olabilir ne Bilseydin değişiklik yapmak kapsama dahil edilecek diğer komutlar vardı ve onlar umursamadı biliyordu ya da sadece bu düzeyde uyumluluk ile ilgilenmiyorsanız, ancak fayda oldukça küçük. Fayda eksikliğinin durumu uygunluk maliyetinden daha fazla yönlendirdiğini hayal ediyorum.
Michael Homer

3
Kabuğun, catkendisinin veya başka herhangi bir yardımcı programın uygulanmasına kesinlikle izin verilir . Ayrıca, sisteme ait diğer yardımcı programların nasıl çalıştığını bilmesine de izin verilir (örneğin , sistemle birlikte gelen harici grepuygulamanın nasıl davrandığını bilebilir ). Bunu yapmak tamamen uygulanabilir, bu yüzden neden yapmadıklarını merak etmek tamamen adil.
Michael Homer

6
@MichaelHomer mesela bunu bilmek nasıl sistem boğulan geldi harici grep uygulaması şimdi davranışı bir bağımlılık kabuk Yani grep. Ve sed. Ve awk. Ve du. Ve binlerce başka yardımcı program yoksa kaç yüz?
Andrew Henle

19
Benim için komutlarımı düzenlemek kabuğumun ne kadar hoş olmadığını gösteriyor.
Azor Ahai

Yanıtlar:


25

2 komut eşdeğer değildir: hata işlemeyi düşünün:

cat <file that doesn't exist> | less Borulu programa aktarılacak boş bir akış üretecek ... böylece hiçbir şey göstermeyen bir ekran ile sona erecek.

< <file that doesn't exist> less çubuğu açamayacak ve daha sonra hiç açmayacak.

Birincisini ikinciye değiştirmeye çalışmak, programı potansiyel olarak boş bir girişle çalıştırmayı bekleyen herhangi bir sayıda betiği kırabilir.


1
Yanıtınızı kabul edildi olarak işaretleyeceğim çünkü bunun iki sözdizimi arasındaki en önemli fark olduğunu düşünüyorum. İle varyant cather zaman boru hattında ikinci komutu yürütür, oysa sadece giriş yönlendirmeli varyant, eğer giriş dosyası eksikse, komutu hiç uygulamaz.
Mikko Rantalainen

Ancak, <"missing-file" grep foo | echo 2yürütülmeyeceğini grepancak yürüteceğini unutmayın echo.
Mikko Rantalainen

51

"Yararsız kullanımı cat", kodunuzu nasıl yazdığınızla ilgili olarak, komut dosyasını çalıştırdığınızda gerçekte neyin çalıştığından daha fazladır. Bu bir tür tasarım karşıtı model , muhtemelen daha verimli bir şekilde yapılabilecek bir şeye gitmenin bir yolu. Yeni bir araç oluşturmak için verilen araçların en iyi şekilde nasıl birleştirileceğini anlamadaki bir başarısızlıktır. Bir boru hattında birkaç sedve / veya awkkomutları bir araya getirmenin bazen aynı anti-paternin bir belirtisi olduğu söylenebilir.

catBir komut dosyasında "yararsız kullanım" örneklerinin düzeltilmesi, öncelikle komut dosyasının kaynak kodunun elle düzeltilmesi sorunudur. ShellCheck gibi bir araç , bariz durumlara dikkat çekerek bu konuda yardımcı olabilir:

$ cat script.sh
#!/bin/sh
cat file | cat
$ shellcheck script.sh

In script.sh line 2:
cat file | cat
    ^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.

Kabuğu bu işlemi otomatik olarak yapmak, kabuk komut dosyalarının doğası nedeniyle zor olacaktır. Bir komut dosyasının yürütme biçimi, ana işleminden miras alınan ortama ve kullanılabilir dış komutların özel uygulamasına bağlıdır.

Kabuğun ne catolduğunu bilmesi gerekmez . Potansiyelinizdeki herhangi bir yerden herhangi bir komut $PATHveya bir fonksiyon olabilir.

Eğer öyle olsaydı yerleşik bir (bazı kabuklarda olabilir), bu komutun olur onun yerleşik sematiğinde bilemez olarak boru hattını yeniden düzenleme yeteneğine sahip catkomutu. Bunu yapmadan önce, orijinalden sonra boru hattındaki bir sonraki komut hakkında varsayımlarda bulunmak zorunda kalacaktı cat.

Standart girdiden okunmanın bir boruya bağlandığında ve bir dosyaya bağlandığında biraz farklı davrandığını unutmayın. Bir boru aranamayabilir, bu yüzden boru hattındaki bir sonraki komutun ne yaptığına bağlı olarak, boru hattının yeniden düzenlenmiş olması halinde farklı olabilir veya olmayabilir (girişin aranıp aranamayacağını tespit edebilir ve varsa veya farklı olup olmadığına karar vermeye çalışabilir. öyle değil, her durumda farklı davranacaktı).

Bu soru ( çok genel anlamda) " Sözdizimi hatalarını kendi kendine düzeltmeye çalışan herhangi bir derleyici var mı? " (Yazılım Mühendisliği StackExchange sitesinde) olmasına rağmen, bu soru açık bir şekilde sözdizimi hataları ile ilgili olsa da, gereksiz tasarım kalıpları hakkındadır. . Niyeti temel alarak kodu otomatik olarak değiştirme fikri büyük oranda aynıdır.


Bir kabuğun ne catolduğunu bilmesi ve boru hattındaki diğer komutlar (as-if kuralı) ve buna göre davranması mükemmel bir şekilde uygundur, burada yok çünkü anlamsız ve çok zor.
Michael Homer

4
@MichaelHomer Evet. Fakat aynı ismin bir fonksiyonuyla standart bir komutu aşırı yüklemesine de izin verilir.
Kusalananda

2
@PhilipCouling Hiçbir boru hattının komut vermediği biliniyorsa kesinlikle uygundur. Kabuğun, yardımcı programları yerleşik veya kabuk işlevleriyle değiştirmesine izin verilir ve bunların yürütme ortamı kısıtlamaları yoktur, bu nedenle dış sonuç ayırt edilemez olduğu sürece. Davan için, farklı olacakcat /dev/tty ilginç olanı . <
Michael Homer

1
@MichaelHomer dış sonuç ayırt edilemez olduğu sürece izin verilir Bu, bu şekilde optimize edilmiş tüm yardımcı programların davranışının asla değişmeyeceği anlamına gelir . Bu nihai bağımlılık cehennemi olmalı.
Andrew Henle,

3
@MichaelHomer Diğer açıklamaların söylediği gibi, elbette , OP'nin girişi göz önüne alındığında, catkomutun çalıştırmadan komutun gerçekte ne yaptığını söylemenin imkansız olduğunu bilmek, kesinlikle mükemmeldir . Hepinizin (ve deniz kabuğunun) bildiği gibi, OP catonun yolunda etkileşimli bir kedi simülasyonu olan bir komut içeriyor, "myfile" sadece depolanmış oyun durumu command1ve command2şu anki oyun seansı ile ilgili bazı istatistikleri işliyor ...
alephzero

34

Çünkü işe yaramaz değil.

Bu durumda cat file | cmd, fd 0(stdin) cmdbir boru olacaktır ve bu durumda cmd <filenormal bir dosya, cihaz vb. Olabilir.

Bir borunun normal bir dosyadan farklı semantikleri var ve semantiği normal bir dosyanın alt kümesi değil :

  • düzenli bir dosya anlamlı bir şekilde kullanılamaz select(2)veya poll(2)silinemez; a select(2)üzerinde her zaman "hazır" dönecektir. epoll(2)Linux'taki gibi gelişmiş arayüzler normal dosyalarla çalışmaz.

  • Linux sistem çağrıları (vardır splice(2), vmsplice(2), tee(2)) borularda sadece çalışma [1]

Yana catçok kullanılır, bu yerleşik olan ekstra süreci önleyecektir bir kabuk halinde uygulanması mümkündür, ancak bu yolda başladıktan sonra, aynı şey en komutları ile yapılabilir - daha yavaş ve clunkier içine kabuk dönüştürme perlveya python. devamı için boru benzeri bir sözdizimi kullanımı kolay olan başka bir betik dili yazmak muhtemelen daha iyidir ;-)

Eğer değil fırsat için yapılmış basit bir örnek isterseniz [1], siz git "stdin'i gelen exec ikili" benim bakabilirsiniz özünü açıklamada bazı açıklamalar ile burada . catUUoC olmadan çalışmasını sağlamak için içine uygulamak , 2 veya 3 kat daha büyük olurdu.


2
Aslında, ksh93 yapar gibi bazı dış komutları uygulamak catiçten.
jrw32982 Monica

3
cat /dev/urandom | cpu_bound_programçalışan read()ayrı bir süreçte sistem çağrıları. Örneğin, Linux'ta, daha fazla rasgele sayı üretmek için gerçek havuz çalışması (havuz boşken) bu sistem çağrısında yapılır, bu nedenle ayrı bir işlem kullanmak, girdi olarak rasgele veri üretmek için ayrı bir CPU çekirdeğinden faydalanmanızı sağlar. Örn: Rastgele basamak içeren 1 GB metin dosyası oluşturmanın en hızlı yolu nedir?
Peter Cordes

4
Daha önemlisi çoğu durumda, lseekişe yaramayacak demektir . cat foo.mp4 | mpv -çalışacak, ancak mpv veya mplayer'ın önbellek tamponundan daha geriye gidemezsiniz. Ancak giriş bir dosyadan yönlendirilmiş olarak yapabilirsiniz. cat | mpv -Bir MP4'ün moovatomunun dosyanın başında olup olmadığını kontrol etmenin bir yoludur , bu nedenle sonuna ve geriye bakmadan oynatılabilir (yani akış için uygunsa). Bir programı, aranamayan dosyalar için yeniden yönlendirme /dev/stdinile çalıştırarak test etmek istediğiniz durumlar hayal etmek kolaydır cat.
Peter Cordes

Kullanırken bu daha doğrudur xargs cat | somecmd. Dosya yolları komut arabelleği sınırının dışına çıkarsa, kesintisiz akışla sonuçlanan birden çok kez xargsçalışabilir cat, xargs somecmddoğrudan kullanılırken başarısız olur çünkü somecmdkesintisiz bir sonuç elde etmek için çoklu katlarda çalıştırılamaz.
tasket

17

Çünkü işe yaramaz kediyi tespit etmek gerçekten çok zor.

Yazdığım bir kabuk betiğim vardı

cat | (somecommand <<!
...
/proc/self/fd/3
...
!) 0<&3

Kabuk betiği, çalıştırıldığı catiçin kaldırıldıysa üretimde başarısız oldu su -c 'script.sh' someuser. Görünüşe göre gereksiz catolan, standart girişin sahibinin betiğin çalıştığı kullanıcı olarak değişmesine neden oldu, böylece yeniden /procçalıştı.


Bu durum oldukça kolay olacaktır, çünkü basit bir modeli catizleyen basit bir modeli izleyen tam bir parametredir, bu nedenle kabuk caten iyi duruma getirilmiş kısayol yerine gerçek yürütülebilir dosya kullanmalıdır. Yine de, gerçek süreçler için muhtemelen farklı referanslar veya standart olmayan standartlar hakkında iyi bir nokta.
Mikko Rantalainen

13

tl; dr: Mermiler otomatik olarak yapmaz çünkü maliyetler muhtemel faydaları aşar.

Diğer cevaplar stdin'in boru olması ile dosya olması arasındaki teknik farklılığa işaret etti. Bunu akılda tutarak, kabuk aşağıdakilerden birini yapabilir:

  1. catDosyayı v. Boru ayrımını koruyarak yerleşik olarak uygulayın . Bu, bir uygulayıcının ve belki de bir çatalın maliyetini düşürür.
  2. Dosya / boru önemli olup olmadığını görmek için kullanılan çeşitli komutların bilgisi ile boru hattının tam bir analizini yapın, sonra buna göre hareket edin.

Daha sonra, her bir yaklaşımın maliyetlerini ve faydalarını göz önünde bulundurmalısınız. Yararları yeterince basit:

  1. Her iki durumda da, bir exec (kaçınmak cat)
  2. İkinci durumda, yönlendirme ikamesi mümkün olduğunda, bir çataldan kaçınılmalıdır.
  3. Bir boru kullanmanız gereken durumlarda, bazen bir çatal / vforktan kaçınmak mümkün olabilir , ancak çoğu zaman bu mümkün olmayabilir. Bunun nedeni, kedi eşdeğerinin, boru hattının geri kalanıyla aynı anda çalışması gerekmesidir.

Bu nedenle, özellikle de çatalı engelleyebiliyorsanız, CPU zamanından ve hafızasından biraz tasarruf edersiniz. Elbette, bu zaman ve hafızadan sadece özellik gerçekten kullanıldığında tasarruf edersiniz. Ve sadece çatal / çalışma zamanını gerçekten kurtarıyorsunuz; daha büyük dosyalarda, zaman çoğunlukla G / Ç zamanıdır (yani, bir dosyayı diskten okuyan kedi). Yani şunu sormak zorundasınız: catperformansın gerçekten önemli olduğu kabuk senaryolarında ne sıklıkla kullanılır (işe yaramaz olarak)? Bunu diğer ortak kabuk yerleşimleriyle karşılaştırın - önemli olan yerlerde kullanılan sıklıkta bir onda bile kullanıldığını testhayal etmek zor . Bu bir tahmin, ölçmedim, bu herhangi bir uygulama denemesinden önce yapmak isteyeceğiniz bir şey. (Ya da benzer şekilde, bir başkasından örneğin bir özellik isteğinde uygulanmasını istemek.)cattest

Sonra sorarsanız: masrafları nelerdir. Akla gelen iki maliyet (a) kabuğunda, büyüklüğünü artıran (ve dolayısıyla hafıza kullanımı) daha fazla bakım çalışması gerektiren ilave kod; böcekler, vb. İçin başka bir nokta; ve (b) geriye dönük uyumluluk sürprizleri, POSIX cat, örneğin, GNU coreutils catgibi birçok özelliği göz ardı eder cat;

  1. Ek yerleşik seçenek büyük olasılıkla o kadar da kötü değil - bir grubun zaten bulunduğu yere bir tane daha ekleyerek. Yardımcı olacağını gösteren bir profil verisine sahipseniz, muhtemelen en sevdiğiniz kabuğun yazarlarını eklemeye ikna edebilirsiniz.

  2. Boru hattını analiz etmeye gelince, kabukların şu anda böyle bir şey yaptığını sanmıyorum (birkaçı bir boru hattının sonunu biliyor ve bir çataldan kaçınabilir). Temel olarak, kabuğa (ilkel) bir optimizer ekleyecektiniz; optimize ediciler genellikle karmaşık kodlar ve birçok hata kaynağı olarak ortaya çıkıyor. Ve bu hatalar şaşırtıcı olabilir - kabuk komut dosyasındaki ufak değişiklikler, hatadan kaçınarak veya tetikleyerek ortaya çıkabilir.

PostScript: Kedinin işe yaramaz kullanımlarına benzer bir analiz uygulayabilirsiniz. Yararları: okunması daha kolay (eğer bir komut argüman olarak bir dosya alacaksa, muhtemelen değil). Maliyetler: ekstra çatal ve exec (eğer komut1 argüman olarak bir dosyayı alabilirse, muhtemelen daha fazla kafa karıştırıcı hata mesajları olabilir). Analizin, işe yaramazca kedi kullanmanı söylerse, devam et.


10

catKomut kabul edebilir -için bir işaretleyici olarak Stdin . ( POSIX , " bir dosya ise '-', kedi programı sırasında bu noktada standart girdiden okunur olacaktır. ") Bu basit bir dosyanın kullanım veya izin veren standart giriş aksi takdirde bu izin istendiği durumda.

Kabuk argümanının $1olduğu şu iki önemsiz alternatifi düşünün -:

cat "$1" | nl    # Works completely transparently
nl < "$1"        # Fails with 'bash: -: No such file or directory'

Başka bir zaman catyararlıdır, yalnızca kabuk sözdizimini sürdürmek için kasıtlı olarak no-op olarak kullanıldığı yerdir:

file="$1"
reader=cat
[[ $file =~ \.gz$ ]] && reader=zcat
[[ $file =~ \.bz2$ ]] && reader=bzcat
"$reader" "$file"

Son olarak, UUOC'nin gerçekten doğru bir şekilde söylenebileceği tek zamanın, normal catbir dosya olduğu bilinen bir dosya adıyla kullanıldığında (yani bir cihaz veya boru kullanılmadığında) ve komuta hiçbir bayrak verilmediğine inanıyorum:

cat file.txt

Başka bir durumda, catkendisinin taşıtlıkları gerekebilir.


6

Cat komutu, kabuğun mutlaka yapamayacağı şeyleri yapabilir (veya en azından kolayca yapamaz). Örneğin, sekmeler, satır başları veya yeni satırlar gibi görünmeyen karakterleri yazdırmak istediğinizi varsayalım. * * Sadece kabuk yerleşik komutları ile bunu yapmanın bir yolu olabilir, ama başımın üstünde hiçbir şey düşünemiyorum. Kedinin GNU versiyonu bunu -Aargümanla veya -v -E -Targümanlarla yapabilir (kedinin diğer versiyonları hakkında bilgim yok). Ayrıca, her bir satırı bir satır numarası ile önek olarak kullanabilirsiniz -n(eğer GNU olmayan sürümler bunu yapabiliyorsa IDK).

Kedinin bir başka avantajı da kolayca birden fazla dosyayı okuyabilmesidir. Bunu yapmak için, bir basit yazabilirsiniz cat file1 file2 file3. Aynı şeyi bir kabukla yapmak, dikkatlice hazırlanmış bir döngü büyük olasılıkla aynı sonucu elde etse de, işler zorlaşacaktır. Bununla birlikte, bu kadar basit bir alternatif varken böyle bir döngü yazmak için zaman ayırmak istiyor musunuz? Yapmıyorum!

Cat ile dosyaları okumak, muhtemelen cat derlenmiş bir program olduğu için kabuktan daha az CPU kullanır (bariz istisna, yerleşik bir kedi içeren herhangi bir kabuktur). Büyük bir dosya grubunu okurken, bu görünebilir, ancak makinelerimde hiç yapmadım, bu yüzden emin olamıyorum.

Cat komutu, bir komutu yapamayacağı durumlarda standart girişi kabul etmeye zorlamak için de yararlı olabilir. Aşağıdakileri göz önünde bulundur:

echo 8 | sleep

"8" sayısı "uyku" komutu tarafından kabul edilmeyecektir, çünkü hiçbir zaman standart girdi kabul etmeyi kastetmemiştir. Böylece uyku, bu girişi göz ardı eder, tartışmaların eksikliğinden şikayet eder ve çıkar. Ancak, eğer bir tür:

echo 8 | sleep $(cat)

Birçok kabuk bunu genişletecek sleep 8ve uyku çıkmadan önce 8 saniye bekleyecek. Ayrıca ssh ile benzer bir şey yapabilirsiniz:

command | ssh 1.2.3.4 'cat >> example-file'

Bu komut, makinede "komut" dan çıkarılmış olanla 1.2.3.4 adresli örnek dosya ekleme ekini içerir.

Ve bu (muhtemelen) sadece yüzeyi çiziktir. İsteseydim, daha yararlı bir kedi örneği bulabileceğime eminim, ama bu yazı olduğu kadar uzun. Bu yüzden şunu söyleyerek bitireceğim: kabuğundan tüm bu senaryoları (ve diğer birkaçını) tahmin etmesini istemek gerçekten mümkün değil.


Son cümleyi "kolay mümkün değil" ile
bitiririm

3

Bir kullanıcının, catiçinde $PATHtam olarak POSIX olmayan bir içeriğe sahip olabileceğini unutmayın cat(ama belki bir yere bir şeyleri girebilecek bir değişken). Bu durumda, kabuğun çıkarmasını istemezsiniz.

PATH Dinamik değiştirin ve sonra olabilir cat kaç olduğunu düşündüğümüz değil. Hayal ettiğiniz optimizasyonu yaparak bir kabuk yazmak oldukça zor olurdu.

Ayrıca, pratikte cat oldukça hızlı bir programdır. Bundan kaçınmak için birkaç pratik sebep (estetik hariç) vardır.

Ayrıca FOSDEM2018'deki Yann Regis-Gianas'ın mükemmel Ayrıştırma POSIX [s] cehennemi konuşmasına da bakın. Bir kabuğun içinde hayalini kurmaya çalışmaktan kaçınmak için başka iyi nedenler de veriyor.

Performans gerçekten kabuklar için bir sorun olsaydı, birisi karmaşık tüm program derleyici optimizasyonunu, statik kaynak kod analizini ve tam zamanında derleme tekniklerini kullanan bir kabuk önerebilirdi (bu üç alanın onlarca yıllık ilerlemesi ve bilimsel yayınları vardı ve kendini adadı. konferanslar, örneğin SIGPLAN kapsamında ). Ne yazık ki, ilginç bir araştırma konusu olarak, şu anda araştırma kurumları veya girişim kapitalistleri tarafından finanse edilmiyor ve bunun sadece çabaya değmeyeceği sonucuna varıyorum. Başka bir deyişle, kabukları optimize etmek için muhtemelen önemli bir pazar yoktur . Bu tür bir araştırmaya harcayacak yarım milyon avronuz varsa, kolayca yapacak birini bulacaksınız ve bunun değerli sonuçlar vereceğine inanıyorum.

Pratik açıdan, yeniden yazma, performansını artırmak için, daha iyi bir betik dilinde (Python, AWK, Guile, ...) küçük (yüz satır) bir kabuk komut dosyası yapılır. Büyük yazılım kodları yazmak pek de mantıklı değil (pek çok yazılım mühendisliği nedeniyle): yüz satırı aşan bir kod yazarken, daha uygun bir dilde yeniden yazmayı düşünmelisiniz (okunabilirlik ve bakım nedenleriyle) : bir programlama dili olarak kabuk çok zayıf bir dildir . Bununla birlikte, birçok büyük üretilmiş kabuk betiği vardır ve iyi nedenlerden dolayı (örneğin GNU autoconf tarafından üretilen configurekomut dosyaları).

Büyük metinsel dosyalara gelince, onları tek bir argüman catolarak iletmek iyi bir uygulama değildir ve çoğu sysadmins bunu bilir (herhangi bir kabuk betiğinin çalışması bir dakikadan uzun sürerse, onu optimize etmeyi düşünmeye başlarsınız). Büyük gigabayt dosyaları için ise asla bunları işlemek için iyi bir araç.cat


3
"Kaçınılması gereken birkaç pratik sebep" - cat some-huge-log | tail -n 5kaçmayı bekleyenler (nereye tail -n 5 some-huge-logsonuna kadar atlayabilse de, catsadece arka arkaya okur), aynı fikirde olmaz.
Charles Duffy

Yorum cat, büyük bir metin dosyasının onlarca GB aralığında (test için oluşturulmuş) çok uzun zaman aldığını gösterir. Tavsiye etmem.
Sergiy Kolodyazhnyy

1
BTW, re: "optimize kabukları için önemli pazar" - ksh93 olan bir optimize kabuk ve oldukça iyi bir. Bu edilmiş , bir süre başarıyla ticari bir ürün olarak satılmaktadır. (Ne yazık ki, ticari olarak lisanslandırılmış olmak, yeterince yazılı olmayan klonların ve daha az yetenekli ancak ücretsiz olan diğer ücretsiz haleflerin, lisans almak için ödeme yapmak isteyen sitelerin dışındaki dünyayı ele geçirmesine neden oldu; bugün var).
Charles Duffy

(not ettiğiniz spesifik teknikleri kullanmamakla birlikte, açıkçası, bu teknikler , süreç modeli göz önüne alındığında anlam ifade etmiyor ; uyguladığı teknikler, iyi, iyi uygulanmış ve iyi bir etki yaratıyor ).
Charles Duffy

2

@Kusalananda cevap ekleyerek (ve @ alephzero yorum), kedi bir şey olabilir:

alias cat='gcc -c'
cat "$MYFILE" | command1 | command2 > "$OUTPUT"

veya

echo 'echo 1' > /usr/bin/cat
cat "$MYFILE" | command1 | command2 > "$OUTPUT"

Sistemdeki kedinin (kendi başına) veya / usr / bin / kedinin aslında birleştirme aracı olması için hiçbir neden yoktur.


3
Davranışı dışında catPOSIX tarafından tanımlanır ve bu yüzden çılgınca farklı olmamalıdır.
roaima

2
@roaima: Şimdi PATH=/home/Joshua/bin:$PATH cat ...ne yaptığını bildiğinden emin misin cat?
Joshua

1
@Joshua gerçekten önemli değil. İkimiz de biliyoruz cat, geçersiz kılınabilir, ama ikimiz de biliyoruz ki bunun yerine yanlış bir şeyle değiştirilmemesi gerekirdi. Benim yorumum, POSIX'in makul bir şekilde gerçekleşmesi beklenen belirli bir (alt küme) davranışı zorunlu kıldığını gösteriyor. Bazen standart bir yardımcı programın davranışını genişleten bir kabuk betiği yazdım. Bu durumda, kabuk betiği, değiştirilen araç gibi davrandı ve davrandı, ancak ek yetenekleri vardı.
roaima

@Joshua: En platformlarda, kabukları biliyor (ya olabilir dizinleri POSIX komutları uygulamak yürütülebilir tutun hangi biliyoruz). Böylece oyuncu değişikliği genişlemenin ve yolun çözülmesinin sonuna kadar erteleyebilir ve sadece bunun için yapabilirsiniz /bin/cat. (Ve kapatabileceğiniz bir seçenek yapardınız.) Veya catyerleşik bir kabuk ( /bin/catbirden fazla argümana geri dönebilir mi?) Böylece kullanıcılar normal harici sürümü normal sürümü isteyip istemediklerini kontrol edebildiler. yol ile enable cat. Gibi için kill. (Ben bash command catişe yarayacağını düşünüyordum , ama bu yerleşikleri atlamaz)
Peter Cordes

Bir takma ad sağlarsanız, kabuk cato ortamda artık normalden söz etmediğini bilecektir cat. Açıkçası, optimizasyon takma adlar işlendikten sonra uygulanmalıdır. Shell yerleşiklerini, her zaman yolunuza hazır olan sanal dizindeki komutları temsil etmeyi düşünüyorum. Herhangi bir komutun kabuk yerleşik versiyonundan (örneğin test) kaçınmak istiyorsanız, yolu olan bir varyant kullanmanız gerekir.
Mikko Rantalainen

1

Kedi için iki "yararsız" kullanım:

sort file.txt | cat header.txt - footer.txt | less

... burada catdosya ve boru girişini karıştırmak için kullanılır.

find . -name '*.info' -type f | sh -c 'xargs cat' | sort

... burada xargsneredeyse sonsuz sayıda dosya adını kabul edebilir ve cathepsini tek bir akış gibi davranırken gerektiği kadar çalıştırabilirsiniz . Bu doğrudan kullanımın xargs sortolmadığı büyük dosya listeleri için işe yarar .


Bu kullanım durumlarının her ikisinde de, cattam olarak tek bir argümanla çağrılırsa , yalnızca yerleşik adımlarla kabuk yerleşik hale getirilerek önemsiz bir şekilde kaçınılabilir . Özellikle shbir dizginin geçtiği ve doğrudan xargsarayacağı durumda cat, kabuğun yerleşik uygulamasını kullanması mümkün değildir.
Mikko Rantalainen

0

Başka şeylerin yanı sıra, cat-check, kullanımının catgerçekten yararsız olduğu konusunda ek performans ek yükü ve karışıklığı ekler , çünkü IMHO, çünkü bu tür kontroller verimsiz olabilir ve meşru catkullanımla ilgili sorunlar yaratabilir .

Komutlar standart akışlarla ilgilendiğinde, yalnızca standart dosya tanımlayıcılarına okuma / yazma ile ilgilenmeleri gerekir. Komutlar stdin'in aranabilir / aranabilir olup olmadığını bilir , bu bir boru veya dosyayı gösterir.

Karışıma, aslında stdin içeriğinin hangi sürecin sağladığını kontrol edersek, borunun diğer tarafında işlemi bulmamız ve uygun optimizasyon yapmamız gerekir. Bu, Kyle Jones'un Süper Kullanıcı postasındaki gibi kabuğun kendisi ve bu kabuğun kabukları açısından yapılabilir.

(find /proc -type l | xargs ls -l | fgrep 'pipe:[20043922]') 2>/dev/null

bağlantılı gönderide gösterildiği gibi. Bu 3 tane daha komuttur (yani ekstra fork()s ve exec()s) ve özyinelemeli geçişler (çok fazla readdir()arama).

C ve kabuk kaynak kodları açısından, kabuk çocuk sürecini zaten biliyor, bu yüzden özyinelemeye gerek yok, ama ne zaman optimize edeceğimizi ve ne zaman catişe yaramaz olduğunu nasıl bilebiliriz ? Kedinin yararlı kullanımları aslında var gibi

# adding header and footer to file
( cmd; cat file; cmd ) | cmd
# tr command does not accept files as arguments
cat log1 log2 log3 | tr '[:upper:]' '[:lower:]'

Kabuğa bu tür bir optimizasyon eklemek muhtemelen atık ve gereksiz ek yük olacaktır. Kusalanda'nın cevabının daha önce de belirtildiği gibi, UUOC, kullanıcının en iyi sonuçları elde etmek için en iyi komutları nasıl bir araya getirebileceğini anlama konusundaki anlayışsızlığı ile ilgilidir.

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.