Hash komutunun amacı nedir?


118

Eğer çalıştırırsanız hash, karma en son sıfırlandığından beri çalıştırılan tüm komutların yolunu gösterir ( hash -r)

[root@c04c ~]# hash
hash: hash table empty

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   1    /usr/bin/whoami

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   2    /usr/bin/whoami

Man sayfalarına göre, karma amacı:

/ Usr / bin / hash yardımcı programı, mevcut kabuk ortamının bulunan yardımcı programların konumlarını hatırlama şeklini etkiler. Belirtilen bağımsız değişkenlere bağlı olarak, hatırlanan konumlar listesine yardımcı program konumları ekler veya listenin içeriğini temizler. Hiçbir argüman belirtilmediğinde, listenin içeriği hakkında rapor verir. -rSeçeneği hatırlanan tüm konumları unutmak kabuk neden olur.

Kabuğa yerleşik olarak sağlanan yardımcı programlar karma tarafından bildirilmez.

Bir komuta kaç kere girdiğimi görmek dışında, bunun yardımcı programını göremiyorum hash.

Thegeekstuff.com'un en yararlı 15 komutunda bile yer aldı.

Hangi yollarla hashfaydalıdır?

Yanıtlar:


97

hashbir bash yerleşik komutudur. Karma tablo, sonuçları bellekte önbelleğe alarak her komut yazışında bash arama yapmak zorunda kalmamasını sağlayan bir özelliktir $PATH. Tablo, sonuçları açıkça geçersiz kılan olaylarda silinir (değiştirme gibi $PATH).

hashEğer bu sistemin (hangisi hissettiğini nedenle yapmanız gerekenler) nasıl etkileşimde komut adildir.

Bazı kullanım durumları:

  • Gördüğünüz gibi, herhangi bir argüman olmadan yazarsanız, hangi komutlara kaç defa basıldığını gösterir. Bu, hangi komutları en sık kullandığınızı söyleyebilir.

  • Standart olmayan konumlardaki yürütülebilir dosyaları hatırlamak için de kullanabilirsiniz.

Örnek:

[root@policyServer ~]# hash -p /lol-wut/whoami whoami
[root@policyServer ~]# whoami
Not what you're thinking
[root@policyServer ~]# which whoami
/usr/bin/whoami
[root@policyServer ~]# /usr/bin/whoami
root
[root@policyServer ~]#

Çalıştırmak $PATHistediğiniz dizindeki tek bir çalıştırılabilir dosya varsa, bu dizindeki her şeyi dahil etmek yerine sadece adı yazmanız yararlı olabilir (eğer eklerseniz etki olur $PATH).

Bir takma ad genellikle bunu da yapabilir, ancak mevcut kabuğun davranışını değiştirdiğiniz için başlattığınız programlarda eşlenmez. Yalnız çalıştırılabilir bir link, muhtemelen burada tercih edilen seçenektir. hashBunu yapmanın bir yolu.

  • Dosya yollarını hatırlamak için kullanabilirsiniz. Bu, yeni bir çalıştırılabilir dosya daha önceki bir PATHdizinde açılırsa veya mvbaşka bir yere giderse ve bash'ı bulup en son bulduğu yer yerine tekrar bulmaya zorlamak istiyorsanız kullanışlıdır .

Örnek:

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# cp /bin/ls /lol-wut
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /bin/ls
[root@policyServer ~]# hash -d ls
[root@policyServer ~]# ls
default.ldif  newDIT.ldif  notes.txt  users.ldif
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /lol-wut/ls
[root@policyServer ~]#

cpKomut yeni bir sürümü neden lsyürütülebilir önceki skinTenimde göstermek $PATHancak karma tablosunun bir tasfiye tetiklemek yoktu. Kullandığım hash -dseçici olarak giriş temizlemek için lskarma tablosundan. Bash, daha sonra $PATHtekrar bakmak zorunda kaldı ve bunu yaptığında, daha yeni bir yerde buldu ($ PATH'ta daha önce çalışmakta olduğundan daha önce).

$PATHBununla birlikte, bu "çalıştırılabilir yeni konumu bul " davranışını seçmeli olarak çağırabilirsiniz :

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# hash ls
[root@policyServer ~]# hash
hits    command
   0    /lol-wut/ls
[root@policyServer ~]#

Bunu karmaşa tablosundan bir şey yapmak istiyorsan ve başarılı bir şekilde giriş yapıp yapamayacağın% 100 olmasaydı ya da kabuğuna yaptığın bazı değişiklikleri korumak istiyorsan, bunu yapmak isterdin.

Eski haritalardan kurtulmak için, bash'ın bütün karma tablosunu etkin bir şekilde temizleyen hash -r(veya export PATH=$PATH) de yapabilirsiniz .

Bunun gibi birçok küçük durum var. Buna "en faydalı" komutlardan biri diyebilir miyim bilmiyorum ama bazı kullanım durumları var.


'Hash' adının nereden geldiğini merak ediyorum. Peki ya örneğin "önbellek", sonra? :).
Michael,

2
@Michael Çünkü hashkomut dahili olarak eşlemeleri saklamak için bir karma tablosu kullanıyor. en.wikipedia.org/wiki/Hash_table
jlliagre 20

10
Unutulmamalıdır hashdeğildir bash(komutlar yollar karma özelliği gelir da komut SVR2 Bourne kabuk kökenli, spesifik cshdaha önce) ve tüm Bourne benzeri ve POSIX kabuklarında bulunan.
Stéphane Chazelas,

1
export PATH=$PATHTabloyu temizlemek yerine, hash -ryeterli olmalıdır.
ravron

1
Diğer bir kullanım durumu, bir programın ikinci kopyasını $ PATH'nızın daha önceki bir bölümüne yüklerken olur. Gerekir hash -rveya eski sürümü alırsınız çünkü $ PATH değişmedi ve Bash aynı programı daha önceki (daha yüksek öncelikli) bir dizinden yükleyebileceğini fark etmedi. Ayrıntılar için conda.pydata.org/docs/… adresine bakın.
John Zwinck

37

İşte basitleştirilmiş klasik kullanım:

# My PATH contains /home/rici/bin as well as the Usual Suspects:
# (the real one has lots more)
$ echo $PATH
/home/rici/bin:/usr/local/bin:/usr/bin:/bin

# I've installed a program called hello in /usr/local/bin
$ $ cat /usr/local/bin/hello
#!/bin/bash

echo Hello, world. I live at $0

# The program works.
$ hello
Hello, world. I live at /usr/local/bin/hello

# Now I want to create a better hello, just for me. I put it in
# my own bin directory, and according to my PATH, it should come first.
$ cp /usr/local/bin/hello ~/bin/hello

# So now I will try running it
$ hello
Hello, world. I live at /usr/local/bin/hello

# WTF? Oh, forgot to run hash.
# Tell bash to update where to look for hello
$ hash hello
$ hello
Hello, world. I live at /home/rici/bin/hello

# Ah, all is well.

Burada belirtildiği gibi , karma tablosunun seçici güncellemesi, tek bir komutla başlatılabilir hash hello.
Ioannis Filippidis,

@ johntex: tamam, değiştirildi.
rici,

Karma tablonun var olduğunu bilmeden önce garip hatalar için potansiyel düşünün! Karma tablo otomatik olarak yenilendiğinde bir koşullar listesi var mı?
benjimin

@ benji: asla otomatik olarak yenilenmez (bir bütün olarak). Bash'i posix modunda çalıştırırsanız veya setopt -s checkhashbir komut için çalıştırılabilir karması artık mevcut değilse, o komutun özeti girişi güncellenir. Ancak, her bash oturumunun kendi karma tablosunun olduğunu unutmayın; bu nedenle oturumu kapatmak ve yeni bir taneye başlamak hash'ı boşaltır. ( hash -rBunu yapmanın daha kolay bir yolu.)
rici

Güncellenmesi $PATHveya yeni bash terminali başlatılması, hem tabloyu temizlemek için görünür.
benjimin

17

İşte yararlı bir kullanım hash:

hash php 2> /dev/null || hash -p /usr/local/foobar/php/bin/php php 2> /dev/null

Bunun anlamı: php PATH'ta değilse, kullan

/usr/local/foobar/php/bin/

8

Evet, Bash Referans El Kitabı diyor ki:

Dizinlerin $ PATH dizininde tam olarak aranması ancak komutun karma tablosunda bulunmaması durumunda gerçekleştirilir.

Ancak, şu karmaşayı devre dışı bırakabilirsiniz set +h:

-h - Yürütülmeleri için aranan komutları bulun ve hatırlayın. Bu seçenek varsayılan olarak etkindir.

Deneyin:

set +h
hash # prints bash: hash: hashing disabled
echo $? # prints 1

Aynı şey hash -r, hash NAMEvb

(Böyle bir "komutu algılama" bu veya o ) çalışmaz:

set -h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2 # prints nothing

set +h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2 # prints Please install ls

Böyle bir şey yazabilirsiniz:

old_options="$-"
set -h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2
[[ "$old_options" =~ "h" ]] || set +h

veya (@mikeserv sayesinde) herhangi bir yeni değişken atamak veya herhangi bir test yapmak zorunda kalmadan:

set -h -- "-${-:--}" "$@"
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2
set +h "$@"

1
Senin old_optionsişin için - genellikle böyle bir şey yaparım: set -h -- "-${-:--}" "$@"; hash ...; set +h "$@"bu yüzden her şey yeni değişkenler atamak veya herhangi bir test veya herhangi bir şey yapmak zorunda kalmadan otomatik olarak yerine geçer.
mikeserv

5

Bir komutun mevcut olup olmadığını kolayca belirleme:

CMD=gzip
if hash bzip2; then
    CMD=$_
fi
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.