बश में एक निर्देशिका का जनक प्राप्त करना


207

अगर मेरे पास कोई फ़ाइल पथ है जैसे ...

/home/smith/Desktop/Test
/home/smith/Desktop/Test/

मैं स्ट्रिंग कैसे बदलूं, इसलिए यह मूल निर्देशिका होगी?

जैसे

/home/smith/Desktop
/home/smith/Desktop/

4
आप बस ' ..' का उपयोग कर सकते हैं , लेकिन हो सकता है कि जो आपके मन में था वह बिलकुल न हो।
जोनाथन लेफ़लर

जवाबों:


331
dir=/home/smith/Desktop/Test
parentdir="$(dirname "$dir")"

काम करता है अगर वहाँ एक अनुगामी स्लेश है, भी।


14
अंदर उद्धरण महत्वपूर्ण हैं या आप अपने सभी डेटा को ढीला करने वाले हैं
कैटामेथामाइन

10
और जिस वेरिएंट का उपयोग मैं वर्तमान वर्किंग डायरेक्टरी के जनक को प्राप्त करने के लिए कर रहा हूं: parentdir=$(dirname `pwd`)
TheGrimmScientist

3
ध्यान दें, यह विधि "बदसूरत" नामों के लिए असुरक्षित है। "-Rm -rf" जैसा नाम वांछित व्यवहार को तोड़ देगा। शायद "।" होगा भी। मुझे नहीं पता कि यह सबसे अच्छा तरीका है, लेकिन मैंने यहां एक अलग "शुद्धता-केंद्रित" प्रश्न बनाया है: stackoverflow.com/questions/40700119/…
VasiliNovikov

4
@Christopher Shroba हाँ, मैंने उद्धरणों को छोड़ दिया और फिर मेरा HDD आंशिक रूप से मिटा दिया गया। मुझे याद नहीं है कि वास्तव में क्या हुआ है: संभवतः एक अयोग्य व्हाट्सएप डायरेक्टरी ने इसे टारगेट वन की बजाय पैरेंट डायर को मिटा दिया - मेरी स्क्रिप्ट ने / होम / xxx / फ़ोल्डर को मिटा दिया।
catamphetamine

3
ओह ठीक है, इसलिए कमांड के बारे में कुछ भी नहीं है जो किसी भी डेटा को खो जाने का कारण होगा जब तक कि आप पहले से ही एक डिलीट कमांड जारी नहीं कर रहे हैं, है ना? यह केवल उस पथ का मामला था जिसे आप अंतरिक्ष चरित्र पर विभाजित होने और अपेक्षा से बहुत अधिक हटाने की कोशिश कर रहे थे?
क्रिस्टोफर श्रोबा


14

केवल echo $(cd ../ && pwd)उस निर्देशिका में काम करते समय उपयोग करें , जिसका मूल आप जानना चाहते हैं। इस श्रृंखला में ट्रेलिंग स्लैश न होने का अतिरिक्त लाभ भी है।


आप echoयहाँ की जरूरत नहीं है।
gniourf_gniourf

14

स्पष्ट रूप से मूल निर्देशिका केवल डॉट-डॉट फ़ाइल नाम जोड़कर दी गई है:

/home/smith/Desktop/Test/..     # unresolved path

लेकिन आपको हल किया हुआ पथ (किसी भी डॉट-डॉट पथ घटकों के बिना एक पूर्ण पथ) चाहिए:

/home/smith/Desktop             # resolved path

उपयोग करने वाले शीर्ष उत्तरों के साथ समस्या यह dirnameहै कि वे डॉट-डॉट्स के साथ एक पथ में प्रवेश करते समय काम नहीं करते हैं:

$ dir=~/Library/../Desktop/../..
$ parentdir="$(dirname "$dir")"
$ echo $parentdir
/Users/username/Library/../Desktop/..   # not fully resolved

यह अधिक शक्तिशाली है :

dir=/home/smith/Desktop/Test
parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`

आप इसे फ़ीड कर सकते हैं /home/smith/Desktop/Test/.., लेकिन और भी जटिल रास्ते जैसे:

$ dir=~/Library/../Desktop/../..
$ parentdir=`eval "cd $dir;pwd;cd - > /dev/null"`
$ echo $parentdir
/Users                                  # the fully resolved path!

संपादित करें: यदि यह काम नहीं करता है, तो जांच लें कि आपका cdसंशोधन नहीं हुआ है, जैसा कि कभी-कभी आम बात है,

$ which cd
cd is a function  #cd was modified to print extra info, so use "builtin cd" to override
cd ()
{
    builtin cd "$@";
    ls -FGAhp
}
...

का उपयोग करना evalबहुत अच्छा नहीं है यदि उपयोगकर्ता इनपुट को पार्स करने का कोई मौका है जो आपको कहीं रख सकता है जो आप उम्मीद नहीं करते हैं या आपके सिस्टम के खिलाफ खराब चीजें चला सकते हैं। आप के pushd $dir 2>&1 >/dev/null && pwd && popd 2>&1 >/dev/nullबजाय का उपयोग कर सकते हैं eval?
ड्रैगन 88

2
आपको बिल्कुल भी ज़रूरत नहीं है eval: बस करो parentdir=$(cd -- "$dir" && pwd)। चूंकि यह cdएक सबशेल में चलाया जाता है, इसलिए आपको उस स्थान पर cdवापस जाने की आवश्यकता नहीं है जहां हम थे। --यहां मामले में के विस्तार है $dirहाइफ़न से शुरू होता है। &&बस रोकने के लिए है parentdirजब एक गैर खाली सामग्री के लिए cdसफल नहीं हुए।
gniourf_gniourf

8

एक और जवाब के लिए प्रेरणा

मुझे बहुत छोटा, स्पष्ट, गारंटीकृत कोड पसंद है। बोनस बिंदु अगर यह एक बाहरी कार्यक्रम नहीं चलाता है, तो जिस दिन से आपको बड़ी संख्या में प्रविष्टियों को संसाधित करने की आवश्यकता होती है, यह काफी तेजी से होगा।

सिद्धांत

आपके पास क्या गारंटी है और क्या चाहते हैं, इस बारे में निश्चित नहीं है, इसलिए वैसे भी पेश करना।

यदि आपके पास गारंटी है तो आप इसे बहुत कम कोड के साथ कर सकते हैं। अंतिम स्लैश और जो कुछ भी है, उसे काटने के लिए बैश टेक्स्ट प्रतिस्थापन सुविधा का उपयोग करने का विचार है।

मूल प्रश्न के सरल से अधिक जटिल मामलों का उत्तर दें।

यदि पथ बिना किसी स्लैश के समाप्त होने की गारंटी दी जाती है (अंदर और बाहर)

P=/home/smith/Desktop/Test ; echo "${P%/*}"
/home/smith/Desktop

यदि पथ को एक स्लैश के साथ समाप्त होने की गारंटी है (इन और आउट)

P=/home/smith/Desktop/Test/ ; echo "${P%/*/}/"
/home/smith/Desktop/

यदि इनपुट पथ शून्य या एक स्लैश (अधिक नहीं) के साथ समाप्त हो सकता है और आप चाहते हैं कि आउटपुट पथ स्लैश के बिना समाप्त हो जाए

for P in \
    /home/smith/Desktop/Test \
    /home/smith/Desktop/Test/
do
    P_ENDNOSLASH="${P%/}" ; echo "${P_ENDNOSLASH%/*}"
done

/home/smith/Desktop
/home/smith/Desktop

यदि इनपुट पथ में कई बाहरी स्लैश हो सकते हैं और आप चाहते हैं कि आउटपुट पथ स्लैश के बिना समाप्त हो जाए

for P in \
    /home/smith/Desktop/Test \
    /home/smith/Desktop/Test/ \
    /home/smith///Desktop////Test// 
do
    P_NODUPSLASH="${P//\/*(\/)/\/}"
    P_ENDNOSLASH="${P_NODUPSLASH%%/}"
    echo "${P_ENDNOSLASH%/*}";   
done

/home/smith/Desktop
/home/smith/Desktop
/home/smith/Desktop

1
शानदार जवाब। चूंकि ऐसा लगता है कि वह एक स्क्रिप्ट के भीतर से ऐसा करने के लिए एक रास्ता ढूंढ रहा था (स्क्रिप्ट की वर्तमान निर्देशिका ढूंढें और यह माता-पिता है और जहां स्क्रिप्ट रहती है, उसके सापेक्ष कुछ करें) यह एक शानदार उत्तर है और आप इस पर और भी अधिक नियंत्रण रख सकते हैं या नहीं इनपुट में एक अनुगामी स्लैश है या पैरामीटर विस्तार का उपयोग करके नहीं, ${BASH_SOURCE[0]}जिसके खिलाफ स्क्रिप्ट का पूरा रास्ता होगा यदि यह sourceया के माध्यम से खट्टा नहीं था .
ड्रैगन 88

7

यदि /home/smith/Desktop/Test/../आप चाहते हैं:

dirname 'path/to/child/dir'

जैसा कि यहां देखा गया है


1
क्षमा करें, मेरा मतलब है कि एक बैश स्क्रिप्ट की तरह, मेरे पास फ़ाइल पथ के साथ एक चर है
YTKColumba

उस कोड को चलाने से मुझे त्रुटि मिलती है bash: dirname 'Test': syntax error: invalid arithmetic operator (error token is "'Test'")। लिंक किया हुआ कोड भी गलत है।
माइकल हॉफमैन

dirname Testनिर्देशिका से बस चलाने की कोशिश करो Test
जॉन एगलैंड

1

इस बात पर निर्भर करता है कि आपको निरपेक्ष पथ की आवश्यकता है या नहीं, आप एक अतिरिक्त कदम उठाना चाहते हैं:

child='/home/smith/Desktop/Test/'
parent=$(dirname "$child")
abs_parent=$(realpath "$parent")

0

इसका उपयोग करें: export MYVAR="$(dirname "$(dirname "$(dirname "$(dirname $PWD)")")")"यदि आप 4th पेरेंट डायरेक्टरी चाहते हैं

export MYVAR="$(dirname "$(dirname "$(dirname $PWD)")")" यदि आप 3 जनक निर्देशिका चाहते हैं

export MYVAR="$(dirname "$(dirname $PWD)")" यदि आप दूसरी मूल निर्देशिका चाहते हैं


धन्यवाद !, बस मैं क्या देख रहा था।
जोस अबर्का

0

बदसूरत लेकिन कुशल

function Parentdir()

{

local lookFor_ parent_ switch_ i_

lookFor_="$1"

#if it is not a file, we need the grand parent
[ -f "$lookFor_" ] || switch_="/.."

#length of search string
i_="${#lookFor_}"

#remove string one by one until it make sens for the system
while [ "$i_" -ge 0 ] && [ ! -d "${lookFor_:0:$i_}" ];
do
    let i_--
done

#get real path
parent_="$(realpath "${lookFor_:0:$i_}$switch_")" 

#done
echo "
lookFor_: $1
{lookFor_:0:$i_}: ${lookFor_:0:$i_}
realpath {lookFor_:0:$i_}: $(realpath ${lookFor_:0:$i_})
parent_: $parent_ 
"

}

    lookFor_: /home/Om Namah Shivaya
{lookFor_:0:6}: /home/
realpath {lookFor_:0:6}: /home
parent_: /home 


lookFor_: /var/log
{lookFor_:0:8}: /var/log
realpath {lookFor_:0:8}: /UNIONFS/var/log
parent_: /UNIONFS/var 


lookFor_: /var/log/
{lookFor_:0:9}: /var/log/
realpath {lookFor_:0:9}: /UNIONFS/var/log
parent_: /UNIONFS/var 


lookFor_: /tmp//res.log/..
{lookFor_:0:6}: /tmp//
realpath {lookFor_:0:6}: /tmp
parent_: / 


lookFor_: /media/sdc8/../sdc8/Debian_Master//a
{lookFor_:0:35}: /media/sdc8/../sdc8/Debian_Master//
realpath {lookFor_:0:35}: /media/sdc8/Debian_Master
parent_: /media/sdc8 


lookFor_: /media/sdc8//Debian_Master/../Debian_Master/a
{lookFor_:0:44}: /media/sdc8//Debian_Master/../Debian_Master/
realpath {lookFor_:0:44}: /media/sdc8/Debian_Master
parent_: /media/sdc8 


lookFor_: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
{lookFor_:0:53}: /media/sdc8/Debian_Master/../Debian_Master/For_Debian
realpath {lookFor_:0:53}: /media/sdc8/Debian_Master/For_Debian
parent_: /media/sdc8/Debian_Master 


lookFor_: /tmp/../res.log
{lookFor_:0:8}: /tmp/../
realpath {lookFor_:0:8}: /
parent_: /

0

चार्ल्स डफी के विचार / टिप्पणी से शुरू - दिसम्बर 17 '14: 5:32 विषय पर वर्तमान निर्देशिका नाम (पूर्ण पथ के बिना) एक बैश स्क्रिप्ट में प्राप्त करें

#!/bin/bash
#INFO : /programming/1371261/get-current-directory-name-without-full-path-in-a-bash-script
# comment : by Charles Duffy - Dec 17 '14 at 5:32
# at the beginning :



declare -a dirName[]

function getDirNames(){
dirNr="$(  IFS=/ read -r -a dirs <<<"${dirTree}"; printf '%s\n' "$((${#dirs[@]} - 1))"  )"

for(( cnt=0 ; cnt < ${dirNr} ; cnt++))
  do
      dirName[$cnt]="$( IFS=/ read -r -a dirs <<<"$PWD"; printf '%s\n' "${dirs[${#dirs[@]} - $(( $cnt+1))]}"  )"
      #information – feedback
      echo "$cnt :  ${dirName[$cnt]}"
  done
}

dirTree=$PWD;
getDirNames;

0

यदि किसी भी कारण से आप किसी विशिष्ट निर्देशिका को नेविगेट करने में रुचि रखते हैं तो आप भी कर सकते हैं nth_path=$(cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd ../../../ && pwd):। यह 3 अभिभावकों की निर्देशिका देगा


क्यों $ {BASH_SOURCE [0]} सरल के बजाय $ BASH_SOURCE
Nam G VU
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.