जांच लें कि क्या पास की गई बहस बैश में फाइल या डायरेक्टरी है


156

मैं उबंटू में एक बहुत ही सरल स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो मुझे इसे या तो एक फ़ाइलनाम या निर्देशिका को पारित करने की अनुमति देगा, और जब यह एक निर्देशिका है, तो यह फ़ाइल और कुछ और होने पर कुछ विशिष्ट करने में सक्षम होगा। समस्या यह है कि जब निर्देशिका नाम, या शायद फ़ाइलें भी है, तो रिक्त स्थान या अन्य सुरक्षित अक्षर नाम में हैं।

यहाँ नीचे मेरा मूल कोड है, और कुछ परीक्षण।

#!/bin/bash

PASSED=$1

if [ -d "${PASSED}" ] ; then
    echo "$PASSED is a directory";
else
    if [ -f "${PASSED}" ]; then
        echo "${PASSED} is a file";
    else
        echo "${PASSED} is not valid";
        exit 1
    fi
fi

और यहाँ उत्पादन है:

andy@server~ $ ./scripts/testmove.sh /home/andy/
/home/andy/ is a directory

andy@server~ $ ./scripts/testmove.sh /home/andy/blah.txt
/home/andy/blah.txt is a file

andy@server~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt
/home/andy/blah with a space.txt is not valid

andy@server~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/
/home/andy with a space/ is not valid

वे सभी पथ मान्य हैं, और मौजूद हैं।


5
if- elseबाश में निर्माण भी समर्थन करते हैं elif। सिर्फ आपकी जानकारी के लिए।

3
@glenn - उत्सुकता से, चर असाइनमेंट में उद्धरण आवश्यक नहीं हैं।
जॉन कुगेलमैन

जवाबों:


211

वह काम करना चाहिए। मुझे यकीन नहीं है कि यह असफल क्यों हो रहा है। आप अपने चर को ठीक से उद्धृत कर रहे हैं। यदि आप इस स्क्रिप्ट का दोहरे उपयोग करते हैं तो क्या होगा [[ ]]?

if [[ -d $PASSED ]]; then
    echo "$PASSED is a directory"
elif [[ -f $PASSED ]]; then
    echo "$PASSED is a file"
else
    echo "$PASSED is not valid"
    exit 1
fi

डबल वर्ग ब्रैकेट एक बैश एक्सटेंशन है [ ]। इसके लिए चर को उद्धृत करने की आवश्यकता नहीं है, भले ही वे रिक्त स्थान हों।

यह भी प्रयास -eकरने के लायक है: यह जांचने के लिए कि कोई पथ किस प्रकार की फ़ाइल के परीक्षण के बिना मौजूद है।


9

कम से कम झाड़ीदार पेड़ के बिना कोड लिखें:

#!/bin/bash

PASSED=$1

if   [ -d "${PASSED}" ]
then echo "${PASSED} is a directory";
elif [ -f "${PASSED}" ]
then echo "${PASSED} is a file";
else echo "${PASSED} is not valid";
     exit 1
fi

जब मैंने उसे "xx.sh" फाइल में डाला और एक फाइल "xx sh" बनायी, और उसे चलाया, तो मुझे यह मिला:

$ cp /dev/null "xx sh"
$ for file in . xx*; do sh "$file"; done
. is a directory
xx sh is a file
xx.sh is a file
$

यह देखते हुए कि आपको समस्याएँ हैं, आपको स्क्रिप्ट को जोड़कर डीबग करना चाहिए:

ls -l "${PASSED}"

यह आपको दिखाएगा lsकि आप स्क्रिप्ट पास करने वाले नामों के बारे में क्या सोचते हैं।


4

"फ़ाइल" कमांड का उपयोग इसके लिए उपयोगी हो सकता है:

#!/bin/bash
check_file(){

if [ -z "${1}" ] ;then
 echo "Please input something"
 return;
fi

f="${1}"
result="$(file $f)"
if [[ $result == *"cannot open"* ]] ;then
        echo "NO FILE FOUND ($result) ";
elif [[ $result == *"directory"* ]] ;then
        echo "DIRECTORY FOUND ($result) ";
else
        echo "FILE FOUND ($result) ";
fi

}

check_file "${1}"

आउटपुट उदाहरण:

$ ./f.bash login
DIRECTORY FOUND (login: directory) 
$ ./f.bash ldasdas
NO FILE FOUND (ldasdas: cannot open `ldasdas' (No such file or  directory)) 
$ ./f.bash evil.php 
FILE FOUND (evil.php: PHP script, ASCII text) 

FYI करें: काम के ऊपर दिए गए उत्तर लेकिन आप उपयोग कर सकते हैं-अजीब परिस्थितियों में मदद करने के लिए पहले एक वैध फ़ाइल की जाँच करके:

#!/bin/bash

check_file(){
    local file="${1}"
    [[ -s "${file}" ]] || { echo "is not valid"; return; } 
    [[ -d "${file}" ]] && { echo "is a directory"; return; }
    [[ -f "${file}" ]] && { echo "is a file"; return; }
}

check_file ${1}

इसलिए, खाली फाइलें वैध नहीं हैं (क्योंकि -sगैर-रिक्त फ़ाइल के लिए चेक, एक गैर-शून्य आकार के साथ)? और आप किसी ब्लॉक विशेष, चरित्र विशेष, फीफो, आदि के लिए कोई निदान नहीं छापेंगे? शायद लिंक के सबसे अंत में जो कुछ भी है, सिम्बलिंक्स उसका समाधान करता है; टूटे हुए सीमलिंक अधिक समस्याग्रस्त हैं।
जोनाथन लेफ़लर

आप एक संपादन के रूप में क्या सुझाव देते हैं, मैं आपकी टिप्पणी का अनुसरण नहीं कर रहा हूं
माइक क्यू

के --briefझंडे का प्रयोग करें file। यह केवल आउटपुट है directoryजब यह है।
बेरकेंट इपेक

2

प्रयोग -fऔर -dस्विच ऑन /bin/test:

F_NAME="${1}"

if test -f "${F_NAME}"
then                                   
   echo "${F_NAME} is a file"
elif test -d "${F_NAME}"
then
   echo "${F_NAME} is a directory"
else                                   
   echo "${F_NAME} is not valid"
fi

आम तौर पर बोलते हुए, आपको किसी पुराने प्रश्न के नए उत्तर को जोड़ने की जहमत नहीं उठानी चाहिए, जब पहले से उपलब्ध समान उत्तर हों। यदि आपके पास जोड़ने के लिए कुछ चौंकाने वाली नई जानकारी है, लेकिन सभी साधनों का जवाब देना है। लेकिन आपने जो कहा है, वह पहले ही कहा जा चुका है। ( testआम तौर पर एक शेल में निर्मित होता है, हालांकि आमतौर पर एक निष्पादन योग्य भी होता है जैसे कि /bin/test, और भी /bin/[।)
जोनाथन लेफ़लर

1

एक और अधिक सुंदर समाधान

echo "Enter the file name"
read x
if [ -f $x ]
then
    echo "This is a regular file"
else
    echo "This is a directory"
fi

2
कमांड लाइन तर्कों का उपयोग करने के बजाय इनपुट के लिए संकेत देना आमतौर पर "अधिक सुरुचिपूर्ण" नहीं है। आपको परीक्षण में चर को उद्धृत करना चाहिए if [ -f "$x" ]:।
जोनाथन लेफ़लर

1
function check_file_path(){
    [ -f "$1" ] && return
    [ -d "$1" ] && return
    return 1
}
check_file_path $path_or_file

-1

यह काम है:

#!/bin/bash

echo "Enter your Path:"
read a

if [[ -d $a ]]; then 
    echo "$a is a Dir" 
elif [[ -f $a ]]; then 
    echo "$a is the File" 
else 
    echo "Invalid path" 
fi

2
कृपया, क्या आप किसी प्रश्न का उत्तर देते समय कुछ स्पष्टीकरण जोड़ सकते हैं?
सेबेस्टियन टेम्प्रादो

-2
#!/bin/bash                                                                                               
echo "Please Enter a file name :"                                                                          
read filename                                                                                             
if test -f $filename                                                                                      
then                                                                                                      
        echo "this is a file"                                                                             
else                                                                                                      
        echo "this is not a file"                                                                         
fi 

आउटपुट में फ़ाइल नाम को गूंजना सबसे अच्छा है, जैसा कि प्रश्न में कोड है। यह स्पष्ट नहीं है कि फ़ाइल नाम के लिए संकेत देना एक सुधार है। कोड फ़ाइलों, निर्देशिकाओं और 'अन्य' के बीच अंतर नहीं करता है। यदि कोई उत्तर नहीं है, तो किसी पुराने प्रश्न का नया उत्तर जोड़ना ठीक है, या आपके पास जानकारी प्रदान करने के लिए नई जानकारी है। यहाँ ऐसा नहीं है।
जोनाथन लेफ्लर

-2

एक लाइन

touch bob; test -d bob && echo 'dir' || (test -f bob && echo 'file')

परिणाम सच है (0) (dir) या सच (0) (फ़ाइल) या गलत (1) (न ही)


यदि मैं touch bobसाथ देता mkdir bobहूं, तो मुझे आउटपुट मिलता है: dirऔर fileदो लाइनों पर।
जोनाथन लेफ़लर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.