.Test yerine .test olarak yürütün


26

Yürütülebilir bir dosyayla aynı klasördeyim, yürütmek için şunu yazmam gerekir:

./file

Yazmamayı tercih ederim /, çünkü /yazmam zor.

Bir dosyayı yürütmenin daha kolay bir yolu var mı? İdeal olarak sadece bazı basit sözdizimi:

.file

ya da /karakteri başka bir yere yerleştirmek zorunda kalmaktan daha kolay .

Belki de /bindizine bir şey koymanın ya da tercüman için bir takma ad oluşturmanın bir yolu vardır , böylece kullanabildik:

p file

9
Belki xmodmap kullanarak başka bir anahtarla değiş tokuş /? Yani en azından yazmak daha kolay
Guy

26
Bir yan not olarak, çoğunlukla bir dizin ayırıcı olarak Unix'te yaygın/ olarak kullanılmaktadır . Yazmanın daha kolay bir yolunu bulma konusunda muhtemelen daha iyisin.
chrylis

7
@RossPresser Bu soru o zamandan beri çok az mantıklı. ve. / Dosyanın başında, herhangi bir aceminin bilmesi gereken teknik nedenlerden ötürü tamamen farklı iki anlam vardır. /insanların büyük çoğunluğu için yazmak zor değildir ve OP bunu önleyen bir yaralanmaya sahipse, alternatif klavye düzenlerini göz önünde bulundurmalıdırlar, çünkü /terminalde tamamen kaçınmaları mümkün değildir .
JFA

1
@JFA Kıta Avrupası ve Güney Amerika'da kullanılan klavye düzenlerinin çoğunluğu, /herhangi bir yaralanma olmadan bile, yazması oldukça zor olan shift-7'yi kullandı.
nitro2k01

6
Düzenleme geçmişi: " can not Ağ Arayüzü basitçe portu 22. ssh ile uzak ana bilgisayar üzerinden tüm internet sorguları yapmak için talimat neden " ಠ_ಠ
Derek朕會功夫

Yanıtlar:


35

"Riskli" olabilir, ancak sahip olabilirsiniz. PATH'inizde.

Diğerlerinde de belirtildiği gibi, bu tehlikeli olabilir, bu yüzden daima emin olun. PATH'nin başlangıcı yerine sonundadır.


1
Bunun nasıl "riskli" olduğunu gerçekten görmeyin: yolum, linux'tan bu yana uzun zamandır böyle olmuştur ve hiçbir zaman en ufak bir soruna neden olmamıştır.
jamesqf

21
@jamesqf Risklidir, çünkü cddünyaca yazılabilir bir dizine giderseniz ve yolunuzda olmayan bir komutu kullanmaya çalışırsanız, birisinin o yola yazdığı adla (muhtemelen kötü amaçlı) yürütülebilir bir dosya çalıştırabilirsiniz. Yolunuzun .başına koyarsanız , bu çok daha kötü . Bu durumda, bu dizinde lsaramayı denerseniz, denilen kötü amaçlı bir çalıştırılabilir dosya yürütülür ls.
59'da bytesized

2
Lütfen yukarıda belirtilen nedenlerden dolayı bundan kaçının. pKomut daha iyi olurdu.
Guido

11
@jamesqf "Sizin" sisteminiz olduğunda ve sadece siz kullandığınızda, hiç de fena değil. Sorun çok kullanıcılı sistemde ortaya çıkıyor (ve yıllar boyunca birçok Unix yöneticisini tetikledi). Bir ile .erken PATH, yapmak için tüm kötü niyetli bir kullanıcı ihtiyaçlarını sahte damla olduğunu ls"garip bir şeye bakmak", yöneticiye onların dizinde komuta ve ikna ve root erişimi var.
TripeHound

1
testSorunun başlığında olduğu gibi dosya adlandırılırsa işe yaramazsa da iyi bir çözüm (çünkü testbir kabuk yerleşiktir ve muhtemelen sizin de $PATHzaten bir yerde de vardır ).
yellowantphil

71

../en azından modern Bash mermilerinde otomatik olarak tamamlayın (yazın .ve basın Tab), bu nedenle karmaşık veya güvensiz ( PATHdeğişiklik gibi ) bir çözüm kullanmanız gerekmez .

Otomatik tamamlanmadıysa "bash-tamamlama" paketini yüklemeniz gerekebilir.


Emin misiniz? .birden fazla tamamlama adayı vardır: .(geçerli dir), ..(parent dir), .komut (bash için standart olmayan bir takma ad sourcesağlar) ve mevcut herhangi bir nokta dosyası. Belki bash-completionpaket bunu görmezden geliyor; Acımasızca sinir bozucu buluyorum (örneğin, bir makekomut satırında dir isimlerinin sekmesini tamamlamayı imkansız kılıyor ve genellikle gizli kurallarla dolu dosya yapmakla berbat) bu yüzden her zaman onu temizliyorum.
R. ..

3
Denedim ve evet, bu şekilde otomatik tamamlama yapıyor. Neredeyse her durumda normal bir kullanıcının istediği şey: Sanırım çalıştırılabilir olması gereken bir dotfile gördüğümü sanmıyorum, bir alt dizinde bir şeyi çalıştırmak, bir üst dizinde bir şeyi çalıştırmaktan çok daha yaygın ve IMO bunu yapıyor. makehedef bulmak için iyi bir iş .
l0b0

Bash 3.2 ile otomatik olarak tamamlanmaz. Bu bash 4'te yeni olabilir mi?
Calimo

2
@Calimo Bash tamamlamanın son sürümlerinde daha yeni. Temel bir değişiklikten uzak.
lbb0

42

veya .. belki tercümana bashrc dosyasında bir takma isim verilmesi ve ardından basitçe

   p  file

Böyle bir fonksiyon yazmak mümkündür:

p() {
 ./"$@"
}

senin içinde ~/.bashrc. O zaman p app argumentsyerine koşmak mümkün olacak ./app arguments. Bu çözüm, komut dosyaları ve ikili dosyalar dahil olmak üzere her türden yürütülebilir dosya için çalışır.

"$@"fonksiyona aktarılan argümanlar listesine uygun şekilde genişler (tüm özel karakterleri glob veya değişken genişlemeden koruyarak) ve @Scott'un belirttiği gibi , geri kalanını koruyarak ilkine hazırlanacak bashkadar zekidir ./.


Uygulamayı başka bir komut altında çalıştırmak daha az genel olsa da, strace -f p appsistem çağrılarını $(which time) p appgörmek veya ne kadar sürdüğünü görmek gibi. pYürütülebilir bir komut dosyası olarak bu iki özel örnekte daha iyi çalışacağım. Ne çözeltisi işe yarayabilir ldd p appolsa ldd da tam bir yol gerektiren farklılık belki de bu gibi nedenlerle,.
kaynakjedi

Evet, değiştirilmesi p app argsile ./app argsönişlemcisinden çeşit yoluyla kabuk girişi boru gerektirecektir herkese görünmez ve ikame :) istenmeyen bir yerde ortaya çıktığında eğlenceli her türlü neden olacak şekilde
aitap

1
Bu durumda, çevresinde hiçbir teklif olmamalıdır $@? Aksi takdirde programa sadece büyük bir argüman iletecektir.
Kroltan

7
@Kroltan No. $@bir dizidir. İçinde genişletildiğinde ", her parametre ayrı bir kelimeye genişler. $*düşündüğün gibi davranır.
8bittree

3
Bunu gereksiz yere karmaşık hale getirdiğine inanıyorum ve p() { ./"$@"; }tek ihtiyacınız olan şey bu .
Scott

11

Sen koymak olabilir .adresinden Müşteri $PATHörneğin ekleyerek PATH=$PATH:.adresinden Müşteri /etc/profile, sen yürütebileceği bu şekilde filesadece yazılı tarafından filesizin yolunda (örneğin bazı diğer klasörde değilse, /usr/bin/). Bunun genellikle iyi bir fikir olmadığını unutmayın.

Neden kötü: Diyelim ki bir dizinin içeriğine tamamen güvenmediğiniz bir durumdasınız - onu tehlikeli bir yerden yüklediniz ve çalıştırmadan önce araştırmak istediğiniz ya da bazılarına yardım eden bir sysadmin kullanıcı kendi dizinine vb. bakarak dizini listelemek istiyorsunuz, böylece ls yazmayı denersiniz, ancak hata yazım hatası yaparsınız ve bunun yerine sl yazabilirsiniz. Bu kötü niyetli dizinin yazarı bunu öngördü ve 'rm -rf --no-preserve-root /' (veya rootkit yüklemek gibi daha kötü bir şey) çalıştıran "sl" adlı bir kabuk betiği koydu.

(Açıklama için teşekkürler @ Baba)


13
Her ne kadar tamamen katılıyorum olsa da, bunun neden iyi bir fikir olmadığını tam olarak açıklamak gerekir.
ymbirtt

16
Neden kötü: Diyelim ki bir dizinin içeriğine tamamen güvenmediğiniz bir durumdasınız - onu tehlikeli bir yerden yüklediniz ve çalıştırmadan önce araştırmak istediğiniz ya da bazılarına yardım eden bir sysadmin kullanıcı kendi dizinine vb. bakarak dizini listelemek istiyorsunuz, böylece ls yazmayı denersiniz, ancak hata yazım hatası yaparsınız ve bunun yerine sl yazabilirsiniz. Bu kötü niyetli dizinin yazarı bunu öngördü ve 'rm -rf --no-preserve-root /' (veya rootkit yüklemek gibi daha kötü bir şey) çalıştıran "sl" adlı bir kabuk betiği koydu.
Muzer

2
Geçerli dizin $
PATH'nin başındaysa

@Muzer Huuuge tinfoil şapkalar burada.
Sombrero Tavuk

4
@GillBates Gerçek ve potansiyel olarak kötü niyetli kullanıcılarla ya da bir yaşam için şüpheli arşivleri analiz eden biriyle uğraşmak zorunda olan bir sysadmin kadar dikkatli olmanız gereken bir şey. Bunlardan hiçbiri geçerli değilse, o zaman sana katılıyorum. Yine de, bunun içine girmenin iyi bir alışkanlık olduğunu düşünmüyorum, çünkü durumlarınızın ne zaman değişeceğini asla bilemezsiniz, bu işlerden birini elde edersiniz ve kendinizi güvensiz davranışlara güvenmek için eğitmiş olduğunuz için kendinizi sonsuz şekilde lanetlersiniz; )
Muzer

10

Tercümanı arayabilirsin, örneğin

bash test

Bu durumda, senaryo ne shebang satırına (örn. #!/bin/bash) Ne de çalıştırılabilir biti olsa bile çalışır . Ayrıca çalıştırmak için doğru tercümanı bilmeniz gerekecektir. Doğru çevirmen çağırdığınızdan emin olmak için önce örneğin shebang satırını okuyabilirsiniz, örneğin shebang satırı diyorsa

#!/usr/bin/env python3

arayacaksın

python3 test

7
tercüman sadece kodu yorumlar, ikili dosyaları çalıştırmazlar
Mc Kernel

Bu cevap biraz mantıklı çünkü tercümana bashrc dosyasında bir takma ad verilebilir.

5
@McKernel iyi bir nokta, sadece bir tercüman varsa çalışır, derlenmiş çalıştırılabilir dosyalar için değil
Zanna

2
derlenmiş çalıştırılabilirler için bir tercüman var:/lib/ld.so
Dmitry Kudriavtsev

7

Bildiğim kadarıyla, env yolunda dosya dahil etmediğiniz sürece elde etmenin bir yolu yoktur, bu yüzden sadece yazarak çalıştırabilirsiniz: file

.fileişe yaramaz çünkü bu farklı bir dosya adıdır. Bu denilen bir dosya .filedeğil ./file.

İngilizce olmayan düzen belki, çünkü sizin için yazılan eğri yazmak zor olabilir hissediyorum? Bu durumda da başıma geliyor, bu yüzden Windows'ta Alt + Shift tuşlarına basarak klavye düzenimi sık sık ingilizce olarak değiştiriyorum (ssh'dan Linux kullanıyorum)


7

İnsanlar ekleyerek ileri sürmüşlerdir .için PATHo yanlışlıkla dünya yazılabilir dizinde ekilen kötü niyetli bir programı çalıştırmak riski oluşturduğundan tehlikeli olan. Eğer size ait olan bir kaç dizinleri çalıştırılabilir programları var ve sadece sizin tarafından yazılabilir Ama eğer, o zaman güvenli (oldukça güvenli?) Var koymak olanlar yönetmen (ler) içine PATHgibi bir satır ekleyerek,

PATH=$PATH:~/dev/myprog1:~/dev/myprog2

sizin için ~/.bashrcdosyanın. Elbette bu, bir programı bu dizinlerden birinden dosya sisteminin herhangi bir yerinden çalıştırabileceğiniz anlamına gelir. Örneğin, yazıp cd /etcyazabilirsiniz foove çalıştırılabilir ~/dev/myprog1/foo. Bu, dizinlerin birinde birden fazla programda aynı ada sahip programların bulunamaması gibi küçük dezavantajlara sahiptir. Özellikle, foo her ikisinde de programlanmışsa ~/dev/myprog1ve ~/dev/myprog2bir yol belirtme dışında ikincisini çalıştıramazsınız. Aynı şekilde bir ~/dev/myprog1/cat- varsa - ama neden istiyorsun?


Başka bir yaklaşım, bunu yaptığınız birkaç programınız varsa, onlar için takma adlar tanımlamaktır:

alias gizmo='./gizmo'
alias gonzo='./gonzo'

Ya da diğer isimleri arayabilir .gizmove .gonzo daha sezgisel bulursanız.

Aslında, bunun bir dereceye kadar, .içine koymakla aynı güvenlik riski vardır PATH. Kötü niyetli bir kullanıcı sizi okuyabilir .bashrcve takma adlarınızı görebilirse, o zaman çalıştırmanız umuduyla kötü amaçlı yazılım olarak adlandırılan gizmove gonzorastgele dizinlere yerleştirebilir. Bu mutlak yol adlarını kullanmak daha iyidir:

alias gizmo='~/dev/myprog1/gizmo'
alias gonzo='~/dev/myprog2/gonzo'

Bu arada, çalıştırılabilir bir dosyayı adlandırmaktan kaçınmalısınız test, çünkü bu bir shell yerleşik komutudur ve bir programı yalnızca bu yolu kullanarak bir yol ya da başka bir numara belirterek çalıştırabilirsiniz.


Alternatif olarak (bir Makefiles kullanıyorsanız) bir tarif yapabilir ve make gizmoveya yapabilirsiniz make gonzo.
ihato

Üzgünüm, ama bunun soruyla veya cevabımla nasıl bağlantılı olduğunu anladığımdan emin değilim. Eğer OP bir oluşturmasını önermiş Are Makefileiçin eylemler, her dizinde öyle ki make gizmo, sonunda çalışan gizmo ? (1) pBaşlangıçta aitap tarafından uygulanan ve Scott tarafından rafine edilen , soruda önerilen işlevle aynı şeyi yapmanın garip bir yolu gibi görünüyor . (2) Argümanları bu şekilde iletebilir misiniz? ISTM'ye make gizmo arg1 arg2eşdeğerdir make gizmo; make arg1; make arg2.
G-Man

1
(1) Belki de benim varsayım yanlıştır ama bana OP kullanmaktan kaçınmak istiyor belli değil ./içinde her dizinde . Aklımda bir şeyler geliştiriyor ve sadece üretilen programı ./filesık sık çalıştırması gerekiyor . Gerçekten sık sık yerel bir dosya çalıştırması gereken başka bir senaryo düşünemiyorum ve sık sık çalıştırmıyorsa soruyu sormaya zahmet etmedi ( imkansız değil zor dedi ) (2) tam olarak değil argümanları tarifte iletebilirsiniz.
ihato

(1) OP'nin motivasyonunun ve sorusunun kapsamının belirsiz olduğu konusunda hemfikir olabiliriz. (2) Bağlantı için teşekkürler.
G-Man

3

Zanna'nın tercümanlar hakkındaki cevabını genişletmek için (üzgünüm, yorum için cevap yok): yerel çalıştırılabilirler için bir "tercüman" (aka ikili ELF dosyaları) dinamik yükleyicidir ( ld.so), ancak genellikle istediğiniz sözdizimini anlamıyor:

$ /usr/lib/ld-linux-x86-64.so.2 program
program: error while loading shared libraries: program: cannot open shared object file
$ /usr/lib/ld-linux-x86-64.so.2 ./program
<program is launched>

(ayrıca, ld.soyolunuza bağlanmadıysanız, hala /s yazmanız gerekir )


Bu Linux'a özgü, değil mi? Lütfen bunu daha fazla açıklayabilir misiniz, neden işe yarıyor? (Linux) çekirdeğinin ayrıştırmayı yapacağını ve bir ikili dosyayı çalıştırıp çalıştırmayacağına karar vereceğini düşündüm binfmt_misc.
phk

2
@ phk Dosya Linux'a özgüdür, ancak dinamik bir bağlayıcı / yükleyici kavramı değildir. Örneğin, FreeBSD'nin kendine ait bir yeri var /libexec/ld-elf.so.1. Linux'ta, "bir binaryin nasıl çalıştırılacağına karar vermek" kadar basit değildir: binfmt_miscdosyanın formatını sihirli sayılarla (ELF, shebang betiği, CIL) algılar. Bundan sonra, binfmt_elfişleyici çağrılır. ELF başlıklarını ve bölümlerini ayrıştırır; .interpbölüm dinamik yükleyicinin yolunu içerir; bu yükleyici çekirdek tarafından başlatılır, yer değiştirir ve atlar _start. FreeBSD'de (diğerlerinden emin değilsiniz) binfmt yok, ancak prensip +/- benzer.
pastırma

1
Bunun neden işe yaradığına dair @ phk - statik bir bağlantıya ld.sosahip değildir .interpve bağlıdır, bu da dış sembollerini çözmek ve yer değiştirme matematiğini yapmak için başka bir dinamik bağlayıcı / yükleyiciye ihtiyaç duymayacağı anlamına gelir.
pastırma

ISTR Solaris'in de buna eşdeğer bir şeyi var.
G-Man,

3

Bir şeyleri yapılandırmaya başlayabilirsek

mkdir -p ~/.local/bin
cat > ~/.local/bin/x << 'EOF'
#!/bin/sh
N="$1"
shift
exec "./$N" "$@"
EOF
chmod a+x ~/.local/bin/x

Çoğu modern dağıtımlar zaten (eklemek $ PATH içinde ~ / .local / bin bulunur export PATH="$HOME/.local/bin:$PATH"etmek senin ~/.profilesenin yapmazsa). Sonra x fileçalıştırmak için kullanabilirsiniz ./file.

Bir .komut tanımlamaya çalışmayın . Komut mevcut kabukta . scriptzaten çalışıyor script. Bu script, mevcut kabuk için ortam değişkenlerini tanımlamaya izin verir .


3
Burada iyi bir öneri olabileceğini düşünüyorum, ancak bunların hiçbirinin ne yaptığına dair hiçbir açıklama yok. Bunu çözebilirdim, ancak deneyimsiz bir kullanıcının şansı olmazdı.
IMSoP

1 $ kaydırmaya gerek yoktur. Sadece exec "$@".
reinierpost

$ (ln -s /bin/ls my-ls && exec my-ls) # bash: exec: my-ls: not found
sourcejedi

(1) Buna gerek yoktur shift $1; sadece exec ./"$@". (2) Bir kabuk senaryosundan bahsettiğiniz için, insanlara bir .komut tanımlamamalarını tavsiye etmek biraz anlamsız / yanıltıcıdır , çünkü adında bir dosya oluşturmak imkansızdır .. (Adı verilen bir diğer ad veya kabuk işlevini tanımlamak mümkündür ve tavsiye edilmez ..)
Scott

1

Yardımcı komut dosyaları yapmamıza izin verilirse, pwd'yi PATH'a ekleyen bir yardımcı yapabilir, sonra

. pathhelper    #adds pwd to path
file            #now it can be run without ./

Bu "" eklemeyi önler. .profile yolunuzu kirletmek ve her noktada bir noktada çalıştırmak istediğiniz her yolla.

Değiştirilmiş bir PATH ile yeni bir kabuk fırlatan bir yardımcı yaparak bu yaklaşımı bir adım öteye götürebiliriz. Bir dizini parametre olarak alırsa (pwd'yi varsayılan olarak kullanarak), pushdyolu düzenleyen gibi çalışır . Alt kabuktan çıkarken diğer ortam değişkenlerinde herhangi bir değişikliğin kaybolacağına dikkat etmeniz gerekebilir, ancak uzun süren bir kabukta PATH değişkeniniz dağınık olmaz. İş akışlarınıza bağlı olarak bu avantajlı olabilir.

:outer shell prompt$; subshellpathhelper    # launches a subshell with modified PATH
: subshell prompt $ ; file                  # in the subshell it can be run without ./

Ama sanırım onunla koşmak istersen kesebilirsin pushdve popdböylece diğer değişiklikleri kaybedecek bir deniz kabuğu yapmadan aynı değişiklikleri yapabilirler.

pushd --path ~/some/path/    # normal pushd plus adds target to path
file                         # it can be run without ./ until you popd

(Aynısını yapamazsınız cdçünkü bunun bir analogu yok popd.)

Ayrıca PATH girişlerini zorlamak ve patlatmak için özel bir yardımcı çifti de oluşturabilirsiniz. En iyisi aslında kullanım şeklinize bağlıdır.


Aslında, onun gibi bir şey yapabilirsin cd, ama daha ileride: Bir dosya yap .dircmds, ve değiştirmeden hemen sonra kullanılabilir duruma gelmeden önce kullanılabilir olmayan cdkomutları ./.dircmdskullanılamaz hale getirmek için kes.
ShadSterling

-1

. script.shYürütmek istediğiniz komut dosyası geçerli dizinde olduğu sürece sözdizimini kullanabilirsiniz .

Tercüman ile sh veya bash gibi öneki de ekleyebilirsiniz. örnek:bash script.sh


8
. script.shkomut dosyası içeriyorsa exit, beklenmeyen etkilere sahipse, örneğin PATH "geçici olarak" yeniden tanımlandıysa kırılır ; Aynı zamanda sadece şu anki kabuğunuz için scriptler için çalışır
sourcejedi

@sourcejedi exitOnu parantez içine, yani bir alt kabuk içine koyabilirsiniz, ancak doğru, yine de yalnızca aynı kabuktaki komut dosyaları için olurdu.
phk

Soru “çalıştırılabilir bir dosya” diyor. Bunlar bir ikili çalıştırılabilir dosya için çalışmaz; sadece bir senaryo için. İkinci paragrafınız Zanna'nın cevabını çoğaltır .
Scott

Şey, benim kötü, çoğunlukla bash şeyleri icra ediyorum ve bash şeylerini kullandım, bu yüzden bash betiği hakkında konuştuğumuzu varsaydım :)
UltimateByte

Sadece bir komut dosyası için değil, sadece bir Bash komut dosyası için.
Oskar Skog
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.