2013-11-25 5 views
16

शीर्षक कहता है, मैं यह निर्धारित करने की कोशिश कर रहा हूं कि मेरी बैश स्क्रिप्ट को पैरामीटर के रूप में निर्देशिका में पूर्ण पथ या रिश्तेदार फ़ाइल प्राप्त होती है या नहीं। जब मैं या तो एक पूर्ण पथ या निरपेक्ष पथ के साथ मेरी स्क्रिप्ट चलाने

#!/bin/bash 

DIR=$1 

if [ "$DIR" = /* ] 
then 
    echo "absolute" 
else 
    echo "relative" 
fi 

यह कहते हैं::

कुछ कारणों के लिए निम्नलिखित मेरे लिए काम नहीं लगता है

./script.sh: line 5: [: too many arguments 
relative 

कुछ के लिए कारण मैं इस बग को समझने के लिए प्रतीत नहीं कर सकता। कोई विचार?

उत्तर

29

[ ... ] पैटर्न मिलान नहीं करता है। /*/ की सामग्री के लिए विस्तारित किया जा रहा है, इसलिए प्रभावी रूप से आप

if [ "$DIR" = /bin /boot /dev /etc /home /lib /media ... /usr /var ] 

या कुछ इसी तरह की है। इसके बजाय [[ ... ]] का उपयोग करें।

if [[ "$DIR" = /* ]]; then 
+0

यदि मैं यह पथ '/ home/user/folder1 /../ folder2' देता हूं जो सापेक्ष है तो यह आउटपुट करेगा कि यह पूर्ण है जो गलत है। –

+11

एक रिश्तेदार पथ वह है जो वर्तमान कार्यशील निर्देशिका के आधार पर अलग-अलग फ़ाइलों को संदर्भित करता है। वह पथ हमेशा '/ home/user/folder2' को संदर्भित करता है, इसलिए यह एक पूर्ण पथ है। '..' सिर्फ शेल शॉर्टकट नहीं है; यह निर्देशिका प्रणाली के माता-पिता के लिए फ़ाइल सिस्टम में एक बहुत ही वास्तविक प्रविष्टि है। – chepner

4

ShellCheck स्वचालित रूप से बताते हैं कि "[ .. ] can't match globs. Use [[ .. ]] or grep."

दूसरे शब्दों में, का उपयोग

if [[ "$DIR" = /* ]] 

क्योंकि [ एक नियमित रूप से आदेश है, इसलिए /*, पहले से खोल से विस्तार किया जाता है यह

में तब्दील हो यह वह जगह है
[ "$DIR" = /bin /dev /etc /home .. ] 

[[ विशेष रूप से खोल द्वारा संभाला जाता है, एक इस समस्या में नहीं है।

22

बस पहले चरित्र पर परीक्षण:

if [ "${DIR:0:1}" = "/" ] 
+1

'bash' (और' ksh' और 'zsh') में अच्छी तरह से काम करता है, लेकिन संभावित भ्रम से बचने के लिए:' [...] 'और' = ', यह समाधान POSIX-compliant नहीं है (POSIX खोल spec। स्थितित्मक सबस्ट्रिंग निष्कर्षण का समर्थन नहीं करता है)। यदि POSIX अनुपालन एक आवश्यकता नहीं है, इस मामले में, आमतौर पर '[[...]] ':' [[" $ {DIR: 0: 1} "== '/']]' (या यहां तक ​​कि '[[$ {डीआईआर: 0: 1} =='/']] ')। – mklement0

4

लेखन परीक्षण मजेदार है:

#!/bin/bash 

declare -a MY_ARRAY # declare an indexed array variable 

MY_ARRAY[0]="https://stackoverflow.com/a/b" 
MY_ARRAY[1]="a/b" 
MY_ARRAY[2]="/a a/b" 
MY_ARRAY[3]="a a/b" 
MY_ARRAY[4]="/*" 


# Note that 
# 1) quotes around MY_PATH in the [[ ]] test are not needed 
# 2) the expanded array expression "${MY_ARRAY[@]}" does need the quotes 
# otherwise paths containing spaces will fall apart into separate elements. 
# Nasty, nasty syntax. 

echo "Test with == /* (correct, regular expression match according to the Pattern Matching section of the bash man page)" 

for MY_PATH in "${MY_ARRAY[@]}"; do 
    # This works 
    if [[ $MY_PATH == /* ]]; then 
     echo "'$MY_PATH' is absolute" 
    else 
     echo "'$MY_PATH' is relative" 
    fi 
done 

echo "Test with == \"/*\" (wrong, becomes string comparison)" 

for MY_PATH in "${MY_ARRAY[@]}"; do 
    # This does not work at all; comparison with the string "/*" occurs! 
    if [[ $MY_PATH == "/*" ]]; then 
     echo "'$MY_PATH' is absolute" 
    else 
     echo "'$MY_PATH' is relative" 
    fi 
done 

echo "Test with = /* (also correct, same as ==)" 

for MY_PATH in "${MY_ARRAY[@]}"; do 
    if [[ $MY_PATH = /* ]]; then 
     echo "'$MY_PATH' is absolute" 
    else 
     echo "'$MY_PATH' is relative" 
    fi 
done 

echo "Test with =~ /.* (pattern matching according to the regex(7) page)" 

# Again, do not quote the regex; '^/' would do too 

for MY_PATH in "${MY_ARRAY[@]}"; do 
    if [[ $MY_PATH =~ ^/[:print:]* ]]; then 
     echo "'$MY_PATH' is absolute" 
    else 
     echo "'$MY_PATH' is relative" 
    fi 
done 
4

एक और मामले रास्तों ~ (टिल्ड) से शुरू कर दिया है। ~user/some.file या ~/some.file कुछ प्रकार के पूर्ण पथ हैं।

if [[ "${dir:0:1}" ==/|| "${dir:0:2}" == ~[/a-z] ]] 
then 
    echo "Absolute" 
else 
    echo "Relative" 
fi 
संबंधित मुद्दे