मैं अपनी खुद की "शेल कमांड" (उदाहरण के लिए mkdir / cd कॉम्बो) कैसे बना सकता हूं?


41

मैं यह नहीं बता सकता कि कितनी बार मैंने एक कमांड के लिए कामना की है जो दोनों एक डायरेक्टरी बनाए और उस डायरेक्टरी को आगे बढ़ाए। मूल रूप से, मैं निम्नलिखित के बराबर चाहूंगा:

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

लेकिन केवल /arbitrarily/long/pathएक बार टाइप करने पर , कुछ इस तरह:

mk-cd /arbitrarily/long/path

मैंने ऐसा करने के लिए एक स्क्रिप्ट बनाने की कोशिश की, लेकिन यह केवल स्क्रिप्ट के भीतर निर्देशिका को बदलता है। मैं चाहूंगा कि शेल में डायरेक्टरी भी बदल गई हो।

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

मैं यह काम कैसे कर पाऊंगा?


12
के साथ cd, आपने शुरू से ही एक विशेष मामला चुना। : डी
डैनियल बी

2
नहीं वास्तव में क्या मैं खोज रहा था, लेकिन सुपर शांत cd(का उपयोग कर पिछले निर्देशिका के लिए वापसी से संबंधित जानकारी cd -, उपयोग pushdऔर popdएक निर्देशिका के "ढेर" बनाए रखने के लिए): superuser.com/questions/324512/...
क्रिस्टोफर बॉटम्स

8
आप टाइप कर सकते हैं mkdir -p /very/long/path, तो का उपयोग cd, अंतरिक्ष, और फिर Alt + .अंतिम तर्क, यानी dir नाम दोहराने के लिए।
चोराबा

2
उत्तर नहीं, सिर्फ @ चोराओ के समान टिप्पणी: आप भी उपयोग कर सकते हैं mkdir -p /very/long/path; cd !#:2। स्ट्रिंग !#:2तर्क nr तक विस्तारित होगी। 2 (यानी, तीसरा तर्क /very/long/path, जैसा कि गिनती शून्य से शुरू होती है)।
इंगो ब्लेस्च्मिड्ट

3
@IngoBlechschmidt, और भी आसान, क्योंकि यह अंतिम कमांड का अंतिम तर्क है, आप बस उपयोग कर सकते हैं !$। मैं हर समय इस विशेष चाल का उपयोग करता हूं, हालांकि इतिहास विस्तार के साथ आप बहुत कुछ कर सकते हैं
वाइल्डकार्ड

जवाबों:


92

सबसे सरल तरीका एक शेल फ़ंक्शन का उपयोग करना है:

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

इसे .bashrcकिसी अन्य शेल कमांड की तरह ही आपको उपलब्ध कराने के लिए इसे अपनी फ़ाइल में रखें ।

बाहरी स्क्रिप्ट के रूप में काम नहीं करने का कारण cdवर्तमान में चल रही स्क्रिप्ट की निर्देशिका को बदलना है, लेकिन कॉलिंग को प्रभावित नहीं करता है। यह डिजाइन द्वारा है! प्रत्येक प्रक्रिया की अपनी कार्यशील निर्देशिका होती है जो उसके बच्चों को विरासत में मिलती है, लेकिन इसके विपरीत संभव नहीं है।

जब तक एक पाइपलाइन का हिस्सा नहीं, पृष्ठभूमि में या स्पष्ट रूप से एक उपधारा में चलता है, एक शेल फ़ंक्शन एक अलग प्रक्रिया में नहीं चलता है, लेकिन एक ही में, जैसे कि कमांड को सॉर्ट किया गया है। वर्तमान निर्देशिका शेल को किसी फ़ंक्शन द्वारा बदला जा सकता है।

यहाँ &&इस्तेमाल किया जाता है दोनों आज्ञाओं को अलग करने के लिए उपयोग किया जाता है, यदि पहला कमांड सफल होता है ( mkdir), दूसरा एक चलाएं ( cd)। नतीजतन, यदि mkdirअनुरोधित निर्देशिका बनाने में विफल रहता है , तो इसमें जाने की कोशिश करने का कोई मतलब नहीं है। एक त्रुटि संदेश द्वारा मुद्रित किया जाता है mkdirऔर यह बात है।

इसके -pसाथ उपयोग किया गया विकल्प mkdirकिसी भी लापता निर्देशिका को बनाने के लिए इस उपयोगिता को बताने के लिए है जो तर्क के रूप में पारित निर्देशिका नाम के पूर्ण पथ का हिस्सा है। एक पक्ष प्रभाव यह है कि यदि आप पहले से मौजूद निर्देशिका बनाने के लिए कहते हैं, तो mkcdफ़ंक्शन विफल नहीं होगा और आप उस निर्देशिका में समाप्त हो जाएंगे। इसे एक मुद्दा या एक विशेषता माना जा सकता है। पूर्व मामले में, फ़ंक्शन को उस तरह से उदाहरण के लिए संशोधित किया जा सकता है जो केवल उपयोगकर्ता को चेतावनी देता है:

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

-pविकल्प के बिना , प्रारंभिक कार्य का व्यवहार बहुत भिन्न होता।

यदि निर्देशिका बनाने वाली निर्देशिका पहले से मौजूद नहीं है, mkdirतो ऐसा करने से फ़ंक्शन विफल हो जाता है।

यदि निर्देशिका पहले से मौजूद है, तो mkdirभी विफल रहता है और cdकॉल नहीं किया जाता है।

अंत में, ध्यान दें कि सेटिंग / निर्यात PWDव्यर्थ है, क्योंकि शेल पहले से ही आंतरिक रूप से करता है।

संपादित करें: मैंने --फ़ंक्शन के लिए दोनों आदेशों का विकल्प जोड़ा ताकि निर्देशिका का नाम डैश के साथ शुरू हो सके।


5
आपको यह भी जोड़ना चाहिए कि यह कमांड तब तक स्थायी रूप से उपलब्ध नहीं होगी जब तक कि इसे ~/.bashrcअन्य इनिशियलाइज़ेशन स्क्रिप्ट में से एक या नहीं जोड़ा जाता है ।
AFH

क्या टास्क के alias mk-cd 'mkdir -p \!:1; cd \!:1'बिना टास्क के बराबर करने के लिए बैश में कोई रास्ता नहीं है ? या हो सकता है कि मुझे एक्सटेंडेड एलियास की तरह बैश फंक्शन के बारे में सोचना शुरू कर देना चाहिए?
थॉमस पैड्रॉन-मैकार्थी

@ थॉमसपैड्रॉन-मैककार्थी यह cshतर्क पास करने वाला तंत्र बुर्ज शैली के उपनामों के साथ लागू नहीं किया गया है। फ़ंक्शंस वास्तव में जाने का तरीका है, और अधिक लचीला होना।
जलीगेरे

@ थॉमसपैड्रॉन-मैकार्थी - आप इस उत्तर को देखना पसंद कर सकते हैं , जो एक उपनाम (जो की परिभाषा में bar) को दिए गए मापदंडों तक पहुँचने के लिए एक न के बराबर तंत्र प्रदान करता है । एक अन्य विकल्प का उपयोग करना होगा history 1, जैसे कि alias mk-cd='args="$(history 1)" && args="${args#*mk-cd\ }" && mkdir -p "$args" && cd'- यह प्रश्नकर्ता के उदाहरण के लिए ठीक काम करता है, लेकिन एक सामान्य समाधान नहीं है, क्योंकि एक ही लाइन (जैसे आउटपुट को पाइप करना) पर कोई भी अन्य कमांड इसे विफल कर देगा।
AFH

3
@ थॉमसपेड्रॉन-मैकार्थी को आपको टीसीएस के एलियास के बारे में सोचना चाहिए।
गिलेस एसओ- बुराई को रोकना '

32

मैं एक वैकल्पिक समाधान जोड़ना चाहूंगा।

यदि आप इसे या कमांड से जोड़ते हैं तो आपकी स्क्रिप्ट काम करेगी :.source

. mk-cd /arbitrarily/long/path

यदि आप exportस्क्रिप्ट में ऐसा करते हैं तो अनावश्यक है। आप .एक का उपयोग करके टाइपिंग को बायपास कर सकते हैं alias:

alias mk-cd='. mk-cd'

इसका कारण यह है कि एक स्क्रिप्ट आम तौर पर एक उप-शेल में चलती है इसलिए इसका पर्यावरण पूरा होने पर खो जाता है, लेकिन .(या source) इसे वर्तमान शेल में चलाने के लिए मजबूर करता है।

यह तकनीक कमांड अनुक्रमों के लिए उपयोगी हो सकती है जो एक फ़ंक्शन के लिए बहुत जटिल हैं या जो विकास के अधीन हैं और अक्सर संपादित किए जाते हैं: एक बार aliasदर्ज किए जाने के बाद .bash_aliases, आप स्क्रिप्ट को बिना पुनर्संरचना के बिना संपादित कर सकते हैं।

निम्नलिखित पर ध्यान दें: -

यदि आप एक स्क्रिप्ट लिखते हैं जिसे / कमांड के साथ बुलाया जाना चाहिए , तो यह सुनिश्चित करने के दो तरीके हैं:.source

  1. किसी कारण से, एक स्क्रिप्ट जिसके साथ ./ sourceनिष्पादित करने की आवश्यकता नहीं है, निष्पादन योग्य नहीं है, इसलिए बस इस अनुमति को हटा दें और स्क्रिप्ट या तो "$ PATH" में नहीं मिलेगी या एक स्पष्ट पथ के साथ आने पर अनुमति त्रुटि देगी।

  2. वैकल्पिक रूप से, स्क्रिप्ट के शीर्ष पर निम्नलिखित चाल का उपयोग किया जा सकता है:

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

यह काम करता है क्योंकि एक उप-शेल bindमें चेतावनी जारी करता है, हालांकि कोई त्रुटि स्थिति नहीं: इसलिए readइसका उपयोग बिना इनपुट पर त्रुटि देने के लिए किया जाता है।


जानकारी के लिए धन्यवाद .। मैंने . .bashrcअनगिनत बार किया है, लेकिन यह नहीं जानता कि वास्तव में क्या .होता है। क्या यह समान है export?
cst1992

2
@ cst1992 - नहीं, कमांड पूरी तरह से अलग हैं: पर्यावरण के लिए export varआंतरिक चर की प्रतिलिपि बनाता varहै, जहां यह विरासत में मिला है और किसी भी उप-शेल में एक चर के रूप में आयात किया जाता है, लेकिन इसका माता-पिता के खोल पर कोई प्रभाव नहीं पड़ता है। आम तौर पर एक स्क्रिप्ट को चलाने के लिए एक उप-शेल बनाया जाता है, और इसे पूरा करने पर (निर्यात किए गए चर सहित) कोई भी बदलाव खो जाता है। किसी शेल में वैरिएबल सेट करने के लिए स्क्रिप्ट के लिए उस शेल में चलना होता है, और यही वह .काम करता है: स्क्रिप्ट को सब-शेल बनाए बिना रन करें। मजे की बात है कि .जरूरत के हिसाब से चलने वाली लिपियों के लिए निष्पादन योग्य अनुमति नहीं है।
AFH

जानकारी के लिए धन्यवाद। मैं आपसे आग्रह करता हूं कि आप इस जानकारी को अपनी पोस्ट में शामिल करें। यह उपयोगी है, और स्पष्ट रूप से, टिप्पणियों की कोई गारंटी नहीं है कि वे कल होंगे।
cst1992

@ cst1992 - मैंने मूल प्रश्न को संबोधित किया है, लेकिन मैं अपने जवाब को सहायक मुद्दों के साथ अव्यवस्थित नहीं करना चाहता। यदि आप .और exportकमांड्स के स्पष्टीकरण की तलाश कर रहे हैं , तो इस प्रश्न का शीर्षक आपको यहां एक उत्तर की उम्मीद नहीं करेगा, इसलिए मैं अपने उत्तर को वैसे ही रहने दूंगा, लेकिन आपकी टिप्पणी के लिए धन्यवाद।
एएफएच

सामान्य रूप से +1, लेकिन विशेष रूप से उपनाम के लिए। मेरे पास कुछ स्क्रिप्ट्स हैं, जिन्हें खट्टे करने की जरूरत है और मैं हमेशा उन्हें इस तरह से चलाना भूल जाता हूं। उपनाम उस का अच्छी तरह से ख्याल रखता है।
जो

13

एक भी कमांड नहीं है, लेकिन आपको केवल उपयोग किए जाने वाले सभी पथ को फिर से लिखना नहीं है !$(जो शेल इतिहास में पिछले कमांड से अंतिम तर्क है)।

उदाहरण:

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

1

उपनाम बनाकर । अपनी खुद की कमांड बनाने का बहुत लोकप्रिय तरीका।

आप मक्खी पर एक उपनाम बना सकते हैं:

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

बस। यदि आप उस उपनाम को स्थायी रूप से (केवल वर्तमान सत्र नहीं) रखना चाहते हैं, तो उस आदेश को एक dotfile (आमतौर पर ~ / .bash_aliases या ~ / .bash_profile) में रखें।


4
जब तक लंबी निर्देशिका का नाम हार्डकोड किया जाता है, तब तक यह उपनाम बहुत उपयोगी नहीं होगा जब तक कि यह निर्देशिका किसी अन्य प्रक्रिया द्वारा नियमित रूप से नष्ट नहीं हो जाती।
jlliagre

1

पहले से ही जो सुझाव दिया गया है, इसके अलावा, मैं thefuck की सिफारिश करना चाहता हूं । यह गलतियों को ठीक करके आपके शेल प्रक्रिया को सुव्यवस्थित करने के लिए एक पायथन फ्रेमवर्क है। इस ट्वीट से प्रेरित होकर , आपको केवल अपने कॉन्फ़िगर किए गए उपनाम (डिफ़ॉल्ट रूप से fuck) को टाइप करना है और यह आपकी पिछली कमांड को सही करने का प्रयास करेगा। इसका एक सुधार इस प्रकार है:

/etc $ cd somedir
bash: cd: No such file or directory
/etc $ fuck
mkdir somedir && cd somedir
/etc/somedir $ 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.