Bu komut dosyası neden terminalde çalışıyor ancak bir dosyadan çalışmıyor?


19

Bir dosyaya kaydedilen bu kabuk komut dosyası var: bazı temel dize değiştirme yapar.

#!/bin/sh
html_file=$1
echo "html_file = $html_file"
substr=.pdf
pdf_file="${html_file/.html/.pdf}"
echo "pdf_file = $pdf_file"

Komut satırına yapıştırırsam, iyi çalışır:

$ html_file="/home/max/for_pauld/test_no_base64.html"
  echo "html_file = $html_file"
  substr=.pdf
  pdf_file="${html_file/.html/.pdf}"
  echo "pdf_file = $pdf_file"

verir

html_file = /home/max/for_pauld/test_no_base64.html
pdf_file = /home/max/for_pauld/test_no_base64.pdf

Yukarıdaki ekodan çıktı bu - amaçlandığı gibi çalışıyor.

Ama senaryoyu çağırdığımda

$ saucer "/home/max/for_pauld/test_no_base64.html"

Bu çıktıyı alıyorum:

html_file = /home/max/for_pauld/test_no_base64.html
/home/max/bin/saucer: 5: /home/max/bin/saucer: Bad substitution

Betiğim bash'ın farklı bir sürümünü mü kullanıyor? Mesele hattımı değiştirmem gerekiyor mu?


6
Bu parametre genişletmesi bir bashizmdir (iyi, POSIX olmayan): sapınızı değiştirin.
jasonwryan

Teşekkürler! İşe yaradı. Sanırım shve arasındaki fark biraz pusluyum bash. Ben okuyacağım. Eğer bir cevaba yorum yapmak için rahatsız olabilir, o zaman ben doğru işaretleyecektir.
Max Williams

Ayrıntılı cevabı için Duke'a onay verdi, ama yine de teşekkürler.
Max Williams

2
@MaxWilliams: Özetle, sh orijinal bourne kabuğu. Tüm uyumlu komut dosyaları sh için yazılmalıdır. Ancak sonraki birçok kabuk (ör: bash, Bourne Again mermisi) "neredeyse uyumludur" ve bir sürü ekstra incelik katar. Kullandığınız değişiklik gibi. Günümüzde, yalnızca posix özelliklerini kullanarak oldukça güvendesiniz, ancak taşınabilirliğin daha dar bir kümeye bile bağlı olduğunu unutmayın (yani yalnızca sh). Yani genel olarak, #!/usr/bin/env bashshebang olarak kullanın ve dilediğiniz gibi posixly tanımlı ikameler kullanın, ancak taşınabilirlik uyarıları ile. Ve okuyun: unix.stackexchange.com/a/48787/27616
Olivier Dulac

Yanıtlar:


37

Sh nedir

sh(veya Kabuk Komut Dili) POSIX standardında tanımlanan bir programlama dilidir . Birçok uygulamaları vardır ( ksh88, dash, ...). bashayrıca bir uygulama olarak düşünülebilir sh(aşağıya bakınız).

Çünkü shbir uygulama değil, bir belirtim, /bin/shçoğu POSIX sisteminde gerçek bir uygulamaya yönelik bir sembolik bağlantıdır (veya sabit bir bağlantıdır).

Bash nedir

bashshuyumlu bir uygulama olarak başladı (POSIX standardını birkaç yıl geçmesine rağmen), ancak zaman geçtikçe birçok uzantı elde etti. Bu uzantıların çoğu geçerli POSIX kabuk komut dosyalarının davranışını değiştirebilir, dolayısıyla tek başına bashgeçerli bir POSIX kabuk değildir. Aksine, POSIX kabuk dilinin bir lehçesidir.

bash--posixPOSIX uyumlu hale getiren bir anahtarı destekler . Ayrıca çağrılırsa POSIX'i taklit etmeye çalışır sh.

sh = bash?

Uzun süredir, çoğu GNU / Linux sistemine /bin/shişaret /bin/bashediyordu. Sonuç olarak, ikisi arasındaki farkı görmezden gelmek neredeyse güvenli hale gelmişti. Ancak bu son zamanlarda değişmeye başladı.

İşaret /bin/shetmeyen bazı sistem örnekleri /bin/bash(ve /bin/bashhatta bazıları mevcut olmayabilir):

  1. Varsayılan olarak symlink shyapan modern Debian ve Ubuntu sistemleri dash;
  2. Busybox , genellikle Linux sistem açılışında bir parçası olarak çalıştırılır initramfs. ashKabuk uygulamasını kullanır .
  3. BSD'ler ve genel olarak Linux dışındaki tüm sistemler. OpenBSD pdksh, Korn kabuğunun soyundan geliyor. FreeBSD'ler shorijinal UNIX Bourne kabuğunun torunudur. Solaris'in shuzun bir süre POSIX uyumlu olmayan bir özelliği vardır; Heirloom projesinden ücretsiz bir uygulama elde edilebilir .

/bin/shSisteminizde nelere dikkat edeceğinizi nasıl öğrenebilirsiniz ?

Komplikasyon, /bin/shsembolik bir bağlantı veya sert bir bağlantı olabilir. Sembolik bir bağlantıysa, bunu çözmek için taşınabilir bir yol:

% file -h /bin/sh
/bin/sh: symbolic link to bash

Zor bir bağlantıysa deneyin

% find -L /bin -samefile /bin/sh
/bin/sh
/bin/bash

Aslında, -Lbayrak sembolik ve sabit bağları hem kapsar, ancak bu yöntemin dezavantajı taşınabilir olmadığıdır - POSIX gerektirmez find desteklemek için -samefilehem de, seçenek GNU bulmak ve FreeBSD bulmak destekleyeceğini bunu.

Mesele hattı

Sonuçta, «shebang» satırını yazarak hangisini kullanacağınıza karar vermek size kalmış.

Örneğin

#!/bin/sh

kullanacak sh(ve işaret etmek için ne olursa olsun),

#!/bin/bash

kullanacaktır /bin/bashSunulursa, (ve eğer o değil bir hata iletisiyle başarısız). Elbette başka bir uygulama da belirtebilirsiniz, ör.

#!/bin/dash

Hangisini Kullanmalı

Kendi senaryolarım shiçin aşağıdaki nedenlerden dolayı tercih ederim :

  • standartlaştırılmıştır
  • öğrenmesi çok daha basit ve kolaydır
  • POSIX sistemlerinde taşınabilir - sahip olmasalar bile, sahip basholmaları gerekirsh

Kullanmanın da avantajları vardır bash. Özellikleri, programlamayı daha modern ve diğer modern programlama dillerinde programlamaya benzer hale getirir. Bunlar, kapsam dahilindeki yerel değişkenler ve diziler gibi şeyleri içerir. Plain shçok minimalist bir programlama dilidir.


Ayrıntılı cevap için teşekkürler: Debian tabanlı ve /bin/shgerçekten bir sembolik Linux Mint kullanıyorum /bin/dash.
Max Williams

POSIX sh'e bağlı kalmak istiyorsanız, en iyisi tamamen dışarıda bırakılmalıdır: Kabuk komutları dosyasının ilk satırı "#!" Karakterleriyle başlarsa, sonuçlar belirtilmemiş pubs.opengroup.org/onlinepubs/009695399/ yardımcı programlar /…
Daniel Jour

4
@DanielJour Herhangi bir Unix benzeri sistem, shebangs için olağan desteği düşürdüyse, pratik olarak kullanılamaz olacak kadar çok şeyi kıracaktır. POSIX'te belirtilmemiş olsa bile fiili bir standarttır. Tek gerçek uyumluluk sorunu, tercümanlara giden yolun farklı olabilmesidir.
Barmar

23

@ Hunter.S.Thompson'ın mükemmel cevabına ek olarak, betiğin taşınabilir olmayan bölümünün

pdf_file="${html_file/.html/.pdf}"

Bu ${variable/search/replace}bir GNU oluşumudur. Ancak saf POSIX ile kolayca önleyebilirsiniz:

pdf_file="${html_file%.html}".pdf

Hunter sonra, bu shebang değiştirmekten daha iyi bir düzeltme #! /bin/bash


Teşekkürler - Ben "saf" düzeltme olduğunu kabul ediyorum ama bash terminalde rutin olarak kullandığım (varsayılan olarak) olduğu gibi ziyafeti yüklü bash yerine, ve komut dosyaları sadece normal olarak aynı şeyi yapmak daha kolay Komut satırı.
Max Williams

1
@MaxWilliams Elbette, sorun değil. Bu esas olarak Soru-Cevap veritabanı için hazırlanmıştır.
Philippos
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.