'Bash -c' argümanlarını ekle


22

Diyelim ki Bash üzerinden böyle bir komut çalıştırmak istiyorum:

/bin/bash -c "ls -l"

Bash adam sayfasına göre, şöyle de çalıştırabilirim:

#               don't process arguments after this one
#               |   pass all unprocessed arguments to command
#               |   |
#               V   V
/bin/bash -c ls -- -l

ancak işe yaramaz gibi görünüyor (göz ardı ediliyor). Yanlış bir şey mi yapıyorum, yoksa man sayfasını yanlış mı yorumluyorum?

Adamdan alakalı alıntılar:

-C seçeneği varsa, komutlar dizeden okunur. Dizeden sonra argümanlar varsa, bunlar $ 0 ile başlayan konumlandırma parametrelerine atanır.

ve

A - seçeneklerin sonunu işaret eder ve daha fazla seçenek işlemeyi devre dışı bırakır. -'Den sonraki argümanlar dosya adları ve argümanlar olarak değerlendirilir.

Yanıtlar:


33

Adam sayfasını yanlış yorumluyorsun. Öncelikle, --seçeneklerin sonunu işaret etme kısmı ne yapmaya çalıştığınızla alakasızdır. -cGeçersiz kılar o yani hiç bash opsiyonu işleme yoluyla artık gidiyor yani o bu noktadan sonra komut satırına geri kalanı --komutlarına aktarılır olacağını, seçenekler işaretleyici bir sonu olarak bash tarafından işlenmez.

İkinci hata, ekstra argümanların başlatılan kabuk işlemine konumsal parametreler olarak atandığı, komuta argüman olarak geçirilmediğidir. Yani, yapmaya çalıştığınız şey şunlardan biri olarak yapılabilir:

/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar

İlk durumda, parametrelerin yankılanması $0ve $1açıkça ve ikinci durumda, "$@""$ 0 dışındaki tüm konumsal parametreler" kadar normal bir şekilde genişletmek için kullanılması . Bu durumda, $0aynı zamanda kullanılacak bir şeyden geçmek zorunda olduğumuzu unutmayın ; $0Normalde olacağı için “bash” ı seçtim , ama başka bir şey işe yarayacaktı.

Bu şekilde yapıldığında, doğrudan listelediğiniz komuta doğrudan verdiğiniz herhangi bir argümanı iletmek yerine: dökümantasyonun "komut s dizeden okunur " yazdığını not edin , çoğul. Başka bir deyişle, bu şema yapmanıza olanak sağlar:

/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file

Ama, not orijinal hedefe ulaşmak için daha iyi bir yolu kullanmak olabileceğini envyerine bash:

/usr/bin/env -- "ls" "-l"

Bir kabuğun sağladığı özelliklerden hiçbirine ihtiyacınız yoksa, kullanmak için hiçbir neden yoktur - envbu durumda, daha hızlı, daha basit ve daha az yazı yazmanız gerekir. Ve kabuk metacharacters veya boşluk içeren dosya adlarını güvenle işleyeceğinden emin olmak için zor düşünmek zorunda değilsiniz.


3

Amacınızın ne olduğundan emin değilim, ama sadece bir Rube Goldberg makinesi kurmaya çalışıyorsanız - “çok basit bir görevi gerçekleştirmek için kasıtlı olarak aşırı tasarlanmış veya fazla abartılı bir işlem, icat, cihaz veya cihaz karmaşık moda ”- sonra deneyin

sh -c 'ls $0' -l

veya

sh -c 'ls $1' supercalifragilisticexpialidocious -l

ya da

sh -c 'ls -$0' l

Bunların nasıl çalıştığını Godlygeek'in cevabından anlayabilmelisiniz.

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.