Aynı anda hem dizin oluşturmam hem de içine geçmeme izin veren tek bir gömlek var mı?


150

Kendimi bir çok kez tekrarlarken buluyorum:

mkdir longtitleproject
cd longtitleproject

Dizin adını tekrarlamadan tek satırda yapmanın bir yolu var mı? Ben bash buradayım.




1
mkdir longtitleprojectsonracd !^
user262826 26:17

Yanıtlar:


160

Yerleşik bir komut yoktur, ancak mkdirsonra çağırdı bir işlevi kolayca yazabilirsiniz cd:

mkcd () {
  mkdir "$1"
  cd "$1"
}

Bu kodu ~/.bashrcdosyanıza yerleştirin (veya ~/.kshrcksh kullanıcıları veya ~/.zshrczsh kullanıcıları için). Adı verilen bir işlevi tanımlar mkcd. "$1"çalıştırdığınızda, fonksiyonun argümanı ile değiştirilecektir.

Bu basit sürümün birkaç kusuru var:

  • Aynı anda bir alt dizin zinciri oluşturamazsınız. Onar: -pseçeneği için ilet mkdir. (Bu tespit edilmemiş giden bir yazım hatası riskini, örneğin arttıkça bu ya, arzu olabilir veya olmayabilir mkcd mydierctory/newsubmutlu yaratacak mydierctoryve mydierctory/newsuboluşturmak anlamına zaman newsubmevcut iç mydirectory.)
  • Eğer argüman ile başlar, -ancak sadece değilse -, o zaman mkdirve cdbir seçenek olarak yorumlayacaktır. Eğer sadece -, o cdzaman demek için yorumlayacağım $OLDPWD. O geçtiyse +0 veya daha fazla basamaklı sağlandığı sonra cdzsh içinde dizin yığınında bir endeks olarak yorumlayacaktır. İlk sorunu çözebilir, ancak diğer ikisini değil --argümandan önce geçerek düzeltebilirsiniz . ./Göreceli bir yol ise argümana hazırlanarak tüm bu sorunları çözebilirsiniz .
  • mkdirtakip etmez CDPATH, ama cdöyle yapar, yani CDPATHbaşlamayan bir değere .(kuşkusuz sıra dışı bir konfigürasyona) ayarladıysanız , cdsizi daha önce yaratıldığından farklı bir dizine götürebilir. ./Göreceli yollara hazırlık yapmak bunu düzeltir ( CDPATHgöz ardı edilmesine neden olur ).
  • Eğer mkdirbaşarısız, bu yürütmeye çalışır cd. Onar: &&iki komutu ayırmak için kullanın.

Hala oldukça basit:

mkcd () {
  case "$1" in /*) :;; *) set -- "./$1";; esac
  mkdir -p "$1" && cd "$1"
}

Bu sürüm hâlâ bir kenarda yaratılmış olandan cdfarklı bir dizine girme potansiyeline sahip mkdir: argüman sembolik bir bağlantı mkcdiçeriyor ..ve içeri giriyorsa. Geçerli dizin ise, örneğin, /tmp/hereve mylinkbir sembolik bağ için /somewhere/else, daha sonra mkdir mylink/../foooluşturur /somewhere/else/foooysa cd mylink/../fooiçine değişiklikleri foo. Argümandaki sembolik bağları aramak yeterli değildir, çünkü kabuk aynı zamanda kendi geçerli dizinindeki sembolik bağları da takip eder, yani cd /tmp/mylink; mkdir ../foo; cd ../fooyeni dizine ( /somewhere/else/foo) değil içine dönüşür /tmp/foo. Bunun için düzeltme, cdyerleşimin ..önce tüm yol bileşenlerini çözmesine izin vermektir ( foo/..eğerfooyok, bu yüzden mkdirhiçbirini görmeye gerek yok ..).

Hafif kanlı versiyonda bu sağlamlığa geldik:

mkcd () {
  case "$1" in
    */..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
    /*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
    /*) mkdir -p "$1" && cd "$1";;
    */../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
    ../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
    *) mkdir -p "./$1" && cd "./$1";;
  esac
}

(Alıştırma: neden ilk cdarama için bir deniz kabuğu kullanıyorum ?)

Mkdir başarısız olursa, geçerli dizini değiştirmediğinizden emin olmak istiyorum. Cd - veya $ OLDPWD ile tekrar değiştirmek, kabuğun mevcut dizinine geçme iznine sahip değilse yeterli değildir. Ayrıca, cd çağrısı OLDPWD'yi günceller, bu yüzden sadece bir kez yapmak istiyoruz (veya OLDPWD'yi geri yüklemek).


Ayrıca, sözcüğü önceki satırdan yeniden yazmak zorunda kalmamanın daha az özelleşmiş yolları vardır:

  • Tip cd sonra, Esc .(veya Alt+ .) Önceki komutundan son argüman eklemek için.
  • cd !$yürütür cdönceki komuta son argüman üzerinde.
  • UpÖnceki komut satırını geri çağırmak için tuşuna basın , sonra değiştirmek mkdirüzere düzenleyin cd.

Teşekkürler! Esc. benim için en uygun görünüyor, anahtar dizilimin herhangi bir özel anlamı var mı?
metodofaction

Bu sadece "önceki komutun son kelimesini tekrarla" dizisi için Bash (ve miras kalan kshve aynı zamanda çalışan zsh) dizisidir. Çok sık kullanıyorum.
geekosaur

31
@Gilles "Gilles" hesabının aslında bir uzmanlar paneli tarafından paylaşıldığını düşünmeye başladım. ;-)
Keith

@StephaneChazelas /a/b/..//aslında işe yarar ama işe yaramadı /a/b/../c. Sabit. Soruyu daha geniş bir kitleye koydum.
Gilles

1
mkcd() { mkdir -p "$1" && cd "$1"; }zsh de (benim örneğimde) bir sorun gibi görünmüyor. mkdir -p /var/tmp/somewhere/else /tmp/here; cd /tmp/here; ln -s /var/tmp/somewhere/else mylink; mkdir -p mylink/../foo && cd mylink/../foo; pwd(kurulumu ve içerir) /tmp/here/fooneyin yaratıldığını (ve ne beklediğimi) gösterir. bashhatalı şekilde yaratır ve değişir /var/tmp/somewhere/foo.
Adam Katz

134

İhtiyacın olan tek gömlek bu. Başka bir yapılandırma gerekmez:

mkdir longtitleproject && cd $_

$_Değişken, bash, önceki komuta verilen son argümandır. Bu durumda, az önce oluşturduğunuz dizinin adı. Açıklandığı gibi man bash:

_         At  shell  startup,  set to the absolute pathname used to invoke
          the shell or shell script being executed as passed in the  envi
          ronment  or  argument  list.   Subsequently, expands to the last
          argument to the previous command, after expansion.  Also set  to
          the  full  pathname  used  to  invoke  each command executed and
          placed in the environment exported to that command.  When check
          ing  mail,  this  parameter holds the name of the mail file cur
          rently being checked."$_" is the last argument of the previous command.

Kullanım cd $_yerine önceki komuta son argüman almak için cd !$çünkü cd !$önceki komuta son argüman verir kabuk tarihinin :

cd ~/
mkdir folder && cd !$

evden çıkarsın (veya ~ /)

cd ~/
mkdir newfolder && cd $_

Sonunda evde yeni klasörde !! (veya ~ / newfolder)


23
Neden bu dünyada kabul edilen cevap değil
JSmyth

1
Kabul ediyorum @JSmyth, bu yerli kabuk işlevini kullanan bir tek satırlık olduğunu
sming

OP'nin iki komutu kullanmaktan kaçınmaya çalıştığını düşünüyorum. Bu cevap (neredeyse) yapmak kadar geçerli mkdir foo && cd foo, ki kullanışlı değil.
josemigallas

7
OP, dizin ismini tekrar etmeyi gerektirmeyen tek bir gömlek istiyor
Jesús Carrera

Bu, bahsettiğiniz veya dokümanlar / öğreticilerde başkalarının kullandıklarını gördüğünüz geleneksel tek astardır. Aslında burada 3 mükemmel cevap var. Bu, bir @ jordan-harris tarafından ve seçilen cevap. Kurulumunuza ve tercihlerinize göre değişir.
Wade

30

Bu davranışı dizginlemek hiç aklıma gelmezdi, çünkü aşağıdakilere saatlik olarak yaklaşıyorum ...

$ mkdir someDirectory<ENTER>
$ cd !$

bash'ın !$son satırın son kelimesiyle ikame edildiği; yani girdiğiniz uzun dizin adı.

Ek olarak, dosya adı tamamlama böyle durumlarda arkadaşınızdır. Yeni dizininiz klasördeki tek dosyaysa, hızlı bir çift TAByeni dizini yeniden girmeden verir.

Bash'ın diğer ortak görevler gibi komutları çalıştırmanıza izin vermesi harika olsa da, diğer cevapların önerdiği gibi bash'ın sunduğu komut satırı düzenleme özelliklerini öğrenmenin daha iyi olacağını düşünüyorum, böylece başka bir makinede çalışırken sözdizimsel eksik özel komut dosyalarınızın sağladığı şeker.


1
Bunun gibi en önemli baskınlıklar hakkında bilgi edinmek için iyi bir yer var mı?
dominicbri7

@ dominicbri7 Genellikle aynı Googling "bash komut satırı düzenleme" başlığı altında gelen bir üst sonucunda aşağıdaki verir web.mit.edu/gnu/doc/html/features_7.html Daha spesifik olarak,! $ bir Word Designator örneğidir bakınız olan gnu'su. org / software / bash / manual / bashref.html # Word İşaretleri
Rob

17

Gereğince Ne özelleştirmeler verimliliği artırmak için kabuk profilinizde yaptık? , bu nasıl yaparım:

# make a directory and cd to it
mcd()
{
    test -d "$1" || mkdir "$1" && cd "$1"
}

bu, eğer dizin zaten mevcutsa da çalışır.


4
-pMkdir seçeneği hataları bastırır.
Glenn jackman

1
mcd zaten var olan bir komuttur. Az önce bir örnek vermiş olsanız da, kendimi mkcd'den kısa bir harf olduğu için kullandım.
Dharmit

@Dharmit Shah: Mevcut mcdemir nedir? Bu komutu hangi paket veya proje veriyor?
Mikel

2
mtools mcd komutunu sağlar. Adam sayfasında "mcd komutu, MS-DOS diskindeki çalışma dizinini değiştirmek için kullanılır."
Dharmit

13

Oh My Zsh kullanıyorsanız, tam olarak bunu yapan, take adlı bir komut var . Böyle bir şey olurdu.

take myfolder

Aslında bunu kazara buldum. Sadece baktım ve bu hilebazda Oh My Zsh GitHub wiki'den listeleniyor . Oldukça yararlı bir komut ve kendini yaratması çok kolay.


1
Asla bilmiyordum take:) Mükemmel! btw - Oh My Zsh ile iTerm2. Aslında burada 3 mükemmel cevap var. Bu, @ jesús-carrera tarafından yazılan ve seçilen cevap. Kurulumunuza ve tercihlerinize göre değişir.
Wade

3

Ya da anında kısa bir değişken yaratabilir ve iki kez kullanabilirsiniz x = longproject ; mkdir $x ; cd $x- kabul ediyorum ki hala bir shellscript işlevi kullanmaktan daha uzun :)


0

İşte bahsetmeye değer hafif bir değişken:

function mkdir() {
    local dir=$1
    command mkdir "$dir"  &&  cd "$dir"
}

Bunu kendinize ekleyin ~/.bash_profileve mkdirnormal olarak kullanabilirsiniz (bir kez yaptıktan sonra source), şimdi hariç, standart mkdirkomut yerine yukarıdaki işlevi çalıştıracaktır .

Not, bu, Gilles tarafından kabul edilen cevaba göre girdiyi doğrulamaz , ancak yerleşikleri nasıl geçersiz kılabileceğinizi gösterir.

Dokümanlardan (biraz tekrarlayan):

command mkdir [args]ishal mkdirile argsadı geçen tüm kabuk işlevini görmezden mkdir. Yalnızca PATH'de arama yaparak bulunan kabuk yerleşik komutları veya komutları yürütülür. Adında bir kabuk işlevi varsa ls, çalışan command lsişlev içinde dış komutu yerine getirecektir lsyerine yinelemeli işlevi çağırmak

Ben de builtinbenzer bir sonuç elde ettiğime inanıyorum command.


Kesinlikle alıntı yapmalısın$dir
Jeff Schaller

@Jeff, kabul etti, ancak kabul edilen cevabın ihtiyaç duyduğu tüm onaylar var. Ben sadece commandalternatif olarak kullanımını sunuyorum.
Arj

0

BASH, ZSH veya KSH’ye yardımcı işlev ekleme

mkcdTek satırda ortamınıza komut oluşturun

echo -e 'mkcd() {\n mkdir -p "$1" && cd $_\n}' >> ~/.${0//-/}rc && . ~/.${0//-/}rc


-1

Sadece yukarıdaki cevapları otomatik hale getirin ve bir kez çalıştırılabilir bir komut dosyası yaptı:

fun='
mkcd ()
{
    mkdir -p -- "$1" && cd -P -- "$1"
}'

echo "$fun" >> ~/.bashrc

Sadece bunu yeni bir dosyaya kopyalayın mkcd.shve terminal tarafından sadece bir kez çalıştırın bash mkcd.sh. Sonra source ~/.bashrcgeçerli oturumda çalışmasını sağlamak için yürütün .

Bundan sonra, mkcd some_dirdoğrudan bu dizinde oluşturmak ve girmek için kullanabilirsiniz .


Tek amacı ~/.bashrcdosyaya eklemek olan bir komut dosyasını (bir dosyada) yazmayı öneriyorsunuz ( zaten verilen bir cevapla)? Peki bu mkcd.shsenaryoyu oluşturmayı nasıl önerirsin ? Belki bir editörle? Bu sadece düzenlemeden daha fazla iş gibi görünüyor ~/.bashrc. Bunun kabul edilen cevaba göre avantajı nedir? ……………………………………………………………………… PS Bu, kendi kendinize bile denemediğinizi söyleyen sorunlardan dolayı başarısız olacaktır.
Scott

Bunu söylediğim için üzgünüm ama evet cevabımı yazdığım gibi yukarıdaki cevapları kullandım. Çalışıyor. Bana inanmıyorsan, dene. Ve denememekle ilgili olarak, tüm günümü bugün bash ve python komut dosyası yazmak için kullandım.
subtleseeker 11:17

Ne yazdığını denedim. O mu değil çalışır.
Scott
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.