Kendi “shell” komutlarını nasıl yapabilirim (örn. Mkdir / cd combo)?


41

Hem bir dizin oluşturacak hem de bu dizine taşınacak bir komut için kaç kez istediğimi söyleyemem. Temel olarak, aşağıdakilerin eşdeğerini istiyorum:

mkdir -p /arbitrarily/long/path; cd /arbitrarily/long/path

ama sadece bir /arbitrarily/long/pathkez yazmak zorunda kaldım , şöyle bir şey:

mk-cd /arbitrarily/long/path

Bunu yapmak için bir komut dosyası oluşturmayı denedim, ancak yalnızca komut dosyası içindeki dizini değiştirir. Kabuktaki dizinin de değişmesini istiyorum.

#!/bin/bash
mkdir $1
cd $1
export PWD=$PWD

Bu işi nasıl yapabilirim?


12
İle cdbaşından itibaren özel bir dava seçtiniz. : D
Daniel B

2
Ben arıyordum, ama süper serin Tam olarak ne cdlı bilgi (kullanarak önceki dizine dönmek cd -kullanın pushdve popddizinleri bir "yığın" korumak için): superuser.com/questions/324512/...
Christopher Bottoms

8
Sen yazabilirsiniz mkdir -p /very/long/path, sonra kullanmak cd, uzay ve sonra Alt + .dir adının yani son argüman tekrarlamak.
choroba

2
Cevap değil, sadece @ choroba'nınkine benzer bir yorum: Siz de kullanabilirsiniz mkdir -p /very/long/path; cd !#:2. Dize !#:2, nr argümanına genişler. 2 (yani üçüncü argüman /very/long/pathsayım sıfırla başlar).
Ingo Blechschmidt

3
@IngoBlechschmidt, daha da kolay, çünkü son komutun son argümanı, sadece kullanabilirsiniz !$. Bu özel numarayı her zaman kullanırım, ancak tarihin genişlemesiyle yapabileceğiniz çok şey var .
Joker

Yanıtlar:


92

En basit yöntem, bir kabuk işlevi kullanmaktır:

mkcd() {
    mkdir -p -- "$1" && cd -- "$1"
}

.bashrcBaşka bir kabuk komutu gibi sizin için kullanılabilir olmasını sağlamak için dosyanıza yerleştirin.

Dış komut dosyası olarak çalışmamasının nedeni cd, çalışan komut dosyasının geçerli dizinini değiştirir ancak çağrılan dosyayı etkilemez. Bu tasarım gereğidir! Her sürecin kendi çocukları tarafından miras alınan kendi çalışma dizinleri vardır, ancak bunun tersi mümkün değildir.

Bir boru hattının parçası değilse, arka planda veya açıkça bir alt kabukta koşuyorsanız, bir kabuk işlevi ayrı bir işlemde değil, aynı komutta çalıştırılmış gibi çalışır. Geçerli dizin kabuğu daha sonra bir fonksiyonla değiştirilebilir.

&&Burada kullanılan birinci komut başarılı ise (aracı, kullanılan her iki komutları ayırmak için mkdir), ikinci bir çalıştırın ( cd). Sonuç olarak, mkdiristenen dizini oluşturamazsanız, içeri girmeye çalışmanın bir anlamı yoktur. Bir hata mesajı yazdırılır mkdirve bu kadar.

Kullanılan -pseçenek mkdir, bu yardımcı programa, argüman olarak iletilen dizin adının tam yolunun bir parçası olan eksik bir dizin oluşturmasını bildirmek için vardır. Bir yan etkisi, önceden var olan bir dizini oluşturmak istemeniz durumunda, mkcdfonksiyonun başarısız olmaması ve bu dizinde sona ermesidir. Bu bir sorun veya özellik olarak düşünülebilir. Eski durumda, işlev, kullanıcıyı sadece uyaran şekilde değiştirilebiliyor:

mkcd() {
    if [ -d "$1" ]; then
        printf "mkcd: warning, \"%s\" already exists\n" "$1"
    else
        mkdir -p "$1" 
    fi && cd "$1"
}

-pSeçenek olmasaydı, ilk işlevin davranışı çok farklı olurdu.

Oluşturulacak dizini içeren dizin mkdiryoksa, işlev başarısız olur.

Oluşturulacak dizin zaten mevcutsa, mkdirbaşarısız da olur ve cdçağrılmaz.

Son PWDolarak, kabuk zaten dahili olarak yaptığı gibi, ayar / ihracatın anlamsız olduğunu unutmayın .

Düzenleme: --Bir tire ile başlayan bir dizin adına izin vermek için fonksiyonun her iki komuta da seçenek ekledim .


5
Ayrıca, bu komutun ~/.bashrc, diğer başlatma komut dosyalarından birine veya bunlara eklenmeden kalıcı olarak kullanılamayacağını da eklemelisiniz .
AFH

Bash içinde tcsh'nin alias mk-cd 'mkdir -p \!:1; cd \!:1'fonksiyonunu işlevsiz yapmanın bir yolu yok mu? Veya belki de genişletilmiş takma adlar gibi bash fonksiyonlarını düşünmeye başlamalıyım?
Thomas Padron-McCarthy

@ ThomasPadron-McCarthy Bu cshargüman geçiş mekanizması, burne stili takma adları ile uygulanmaz. Fonksiyonlar gerçekten çok daha esnek olma yoludur.
jlliagre

@ ThomasPadron-McCarthy - Bir takma adı geçen parametrelere erişmek için oldukça tanımsız bir mekanizma sağlayan bu cevaba bakmak isteyebilirsiniz (tanımında bar). Başka bir seçenek de, kullanmakta history 1olduğu gibi kullanmaktır alias mk-cd='args="$(history 1)" && args="${args#*mk-cd\ }" && mkdir -p "$args" && cd'- bu, sorgulayanın örneği için iyi çalışır, ancak aynı satırdaki diğer komutların (örneğin, çıktının borulanması) başarısız olmasına neden olacağı gibi genel bir çözüm değildir.
AFH,

3
@ ThomasPadron-McCarthy tcsh'ın takma adlarını kısıtlı işlevler gibi düşünmeye başlamalısınız.
Gilles,

32

Alternatif bir çözüm eklemek istiyorum.

Senaryonuz olacak sen onu çağırmak durumunda işe . veya sourcekomutun:

. mk-cd /arbitrarily/long/path

Bunu yaparsanız export, komut dosyasında gereksizdir. Sen yazarak atlayabilir .bir kullanarak alias:

alias mk-cd='. mk-cd'

Bunun işe yaramasının nedeni, bir betiğin normal olarak bir alt kabukta çalışmasıdır, böylece ortamı tamamlandığında kaybolur, ancak .(veya source) komutu onu geçerli kabukta çalışmaya zorlar.

Bu teknik, bir işlev için çok karmaşık olan veya geliştirilme aşamasında olan ve sık sık düzenlenen komut dizileri için yararlı olabilir: Bir kez aliasgirildiğinde .bash_aliases, betiği yeniden başlatmadan istediğinizde düzenleyebilirsiniz.

Aşağıdakilere dikkat et:-

/ Komutuyla çağırılması gereken bir komut dosyası yazarsanız , bundan emin olmanın iki yolu vardır: -.source

  1. Bazı nedenlerden dolayı çalıştırılan ./ sourceçalıştırılamayan bir komut dosyası çalıştırılabilir, bu nedenle bu izni kaldırın ve komut dosyası "$ PATH" içinde bulunmayacak veya açık bir yolla çağrıldığında izin hatası verecektir.

  2. Alternatif olarak, aşağıdaki numara, betiğin başında kullanılabilir:

bind |& read && { echo 'Must be run from "." or "source" command'; exit 1; }

Bu, bir alt kabuğun bindbir hata durumu olmamasına rağmen bir uyarı readvermesi nedeniyle işe yarıyor : bu nedenle hiçbir girdide hata vermek için kullanılır.


Bilgi için teşekkürler .. Yaptığım . .bashrcsayısız kez, ama tam olarak bilmiyordum .yok. Benzer exportmi?
cst1992

2
@ cst1992 - Hayır, komutlar tamamen farklıdır: export varvardeğişkeni, herhangi bir alt kabuğa değişken olarak miras alındığı ve alındığı ortama kopyalar , ancak bir ana kabuğa etkisi yoktur. Normalde bir betiği çalıştırmak için bir alt kabuk yaratılır ve yaptığı değişiklikler (verilen değişkenler dahil) tamamlandığında kaybolur. Bir betiğin bir kabuktaki değişkenleri ayarlayabilmesi için o kabukta çalışması gerekir ve bu .komutun yaptığı şeydir : betiği bir alt kabuk oluşturmadan çalıştırın. İlginç bir şekilde, betiklerin çalıştırdığı .çalıştırılabilir izinlere sahip olmaları gerekmez.
AFH

Bilgi için teşekkürler. Bu bilgiyi gönderinize eklemeniz için ısrar ediyorum. Bu yararlıdır ve açıkçası, yorumların yarın orada olacağının garantisi yoktur.
cst1992

@ cst1992 - Orijinal soruyu ele aldım, ancak cevabımı yardımcı konularla karıştırmak istemiyorum. .Ve exportkomutlarının bir açıklamasını arıyorsanız , bu sorunun başlığı burada bir cevap beklemenize neden olmaz, bu yüzden cevabım olduğu gibi durmasına izin vereceğim, ancak yorumunuz için teşekkürler.
AFH

Genel olarak +1, ancak özellikle takma ad için. Kaynaklanması gereken birkaç senaryom var ve onları bu şekilde çalıştırmayı her zaman unutuyorum. Takma ad buna çok dikkat eder.
Joe,

13

Tek bir komut değil, ancak yalnızca kullandığınız tüm yolu !$(kabuk geçmişindeki önceki komutun son argümanı olan) yeniden yazmak zorunda değilsiniz .

Örnek:

mkdir -p /arbitrarily/long/path
cd !$

1

Takma adlar oluşturarak . Kendi komutlarınızı yaratmanın çok popüler bir yolu.

Anında bir takma ad oluşturabilirsiniz:

alias myalias='mkdir -p /arbitrarily/long/path; cd /arbitrarily/long/path'

Bu kadar. Bu takma adı kalıcı olarak tutmak istiyorsanız (yalnızca geçerli oturum değil), o zaman bu komutu bir nokta dosyasına (genellikle ~ / .bash_aliases veya ~ / .bash_profile) koyun.


4
Uzun dizin adı kodlanmış olduğundan, bu diğer ad düzenli bir şekilde başka bir işlem tarafından imha edilmedikçe bu takma ad çok yararlı olmaz.
jlliagre

1

Önceden önerilmiş olanlara ek olarak, tavsiyeyi de tavsiye ederim . Hataları düzelterek kabuk sürecinizi kolaylaştırmak için bir Python çerçevesi. Bu tweet'ten ilham alarak yapmanız gereken tek şey yapılandırılmış takma adınızı (varsayılan olarak fuck) yazmaktır ve önceki komutunuzu düzeltmeye çalışır. Düzeltmelerinden biri şu şekilde davranıyor:

/etc $ cd somedir
bash: cd: No such file or directory
/etc $ fuck
mkdir somedir && cd somedir
/etc/somedir $ 
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.