تحقق من وجود دليل في برنامج نصي shell




unix posix (20)

ما هو الأمر الذي يمكن استخدامه للتحقق من وجود دليل أم لا ، داخل نص برمجي shell؟


المزيد من الميزات باستخدام find

  • تحقق من وجود المجلد داخل الدلائل الفرعية:

    found=`find -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where "myDirectory" is.
        # It may contain several lines if there are several folders named "myDirectory".
    fi
    
  • تحقق من وجود مجلد واحد أو عدة مجلدات بناءً على نمط داخل الدليل الحالي:

    found=`find -maxdepth 1 -type d -name "my*"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where folders "my*" have been found.
    fi
    
  • كلا التركيبات. في المثال التالي ، يتحقق من وجود المجلد في الدليل الحالي:

    found=`find -maxdepth 1 -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' is not empty => "myDirectory"` exists.
    fi
    

  1. برنامج نصي بسيط لاختبار ما إذا كان dir أو الملف موجودًا أم لا:

    if [ -d /home/ram/dir ]   # for file "if [-f /home/rama/file]" 
    then 
        echo "dir present"
    else
        echo "dir not present"
    fi
    
  2. برنامج نصي بسيط للتحقق من وجود الدليل أم لا:

    mkdir tempdir   # if you want to check file use touch instead of mkdir
    ret=$?
    if [ "$ret" == "0" ]
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
    

    النصوص المذكورة أعلاه سوف تحقق من وجود دير أم لا

    $? إذا كان الأمر الأخير sucess تقوم بإرجاع "0" آخر غير قيمة صفرية. لنفترض tempdir موجود بالفعل ثم سوف تعطي mkdir tempdir خطأ مثل أدناه:

    mkdir: لا يمكن إنشاء الدليل 'tempdir': الملف موجود


أجد أن الإصدار tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS من test يجعل اختبارات الكتابة المنطقية أكثر طبيعية:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

أو لشيء لا طائل منه تماما:

[ -d . ] || echo "No"

اختتم هذا الجواب كبرنامج نصي shell

أمثلة

$ is_dir ~                           
YES

$ is_dir /tmp                        
YES

$ is_dir ~/bin                       
YES

$ mkdir '/tmp/test me'

$ is_dir '/tmp/test me'
YES

$ is_dir /asdf/asdf                  
NO

# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
  echo "Folder doesnt exist: $DIR";
  exit;
fi

is_dir

function show_help()
{
  IT=$(CAT <<EOF

  usage: DIR
  output: YES or NO, depending on whether or not the directory exists.

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

DIR=$1
if [ -d $DIR ]; then 
   echo "YES";
   exit;
fi
echo "NO";

اكتب هذا الرمز على bash promt

if [ -d "$DIRECTORY" ]; then
  # if true this block of code will execute
fi

تجد أدناه يمكن استخدامها ،

find . -type d -name dirname -prune -print

تحقق مما إذا كان الدليل موجودًا ، فاجعله آخر

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY

شكل أقصر:

[ -d "$DIR" ] && echo "Yes"

في الواقع ، يجب عليك استخدام العديد من الأدوات للحصول على نهج مضاد للرصاص:

DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # now you're testing
    echo "It's a dir";
fi

لا داعي للقلق بشأن المسافات والأحرف الخاصة طالما أنك تستخدم "${}" .

لاحظ أن [[]] ليست محمولة مثل [] ، ولكن بما أن معظم الناس يعملون مع الإصدارات الحديثة من Bash (حيث أن معظم الناس لا يعملون حتى مع سطر الأوامر: - p) ، فإن الفائدة أكبر من مشكلة.


للتحقق مما إذا كان هناك دليل موجود في برنامج نصي shell ، يمكنك استخدام ما يلي:

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

أو للتحقق من عدم وجود دليل:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

ومع ذلك ، وكما يشير Jon Ericson ، قد لا تعمل الأوامر اللاحقة كما هو مقصود إذا لم تأخذ في الاعتبار أن الارتباط الرمزي إلى الدليل سيمر أيضًا هذا الشيك. على سبيل المثال تشغيل هذا:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

سوف ينتج رسالة الخطأ:

rmdir: failed to remove `symlink': Not a directory

لذلك قد يتعين التعامل مع الارتباطات الرمزية بشكل مختلف ، إذا كانت الأوامر اللاحقة تتوقع أدلة:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

لاحظ بشكل خاص علامات الاقتباس المزدوجة المستخدمة في التفاف المتغيرات ، والسبب في ذلك هو تفسير 8jean في إجابة أخرى .

إذا كانت المتغيرات تحتوي على مسافات أو أحرف أخرى غير معتادة ، فمن المحتمل أن تتسبب في فشل البرنامج النصي.


للتحقق من أكثر من دليل واحد ، استخدم هذا الرمز:

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi

هل فكرت في القيام بكل ما تريد القيام به في if كنت تبحث قبل أن تقفز؟

إذا كنت تريد التحقق من وجود دليل قبل إدخاله ، فجرّب القيام بذلك:

if pushd /path/you/want/to/enter; then
    # commands you want to run in this directory
    popd
fi

إذا كان المسار الذي تعطيه لـ pushd موجودًا ، pushd بـ 0 ، مما يعني أنه سيتم تنفيذ الجزء التالي من العبارة. إذا لم يكن موجودًا ، فلن يحدث شيء (بخلاف بعض المخرجات التي تقول أن الدليل غير موجود ، وهو على الأرجح تأثير جانبي مفيد لأي طريقة لتصحيح الأخطاء).

يبدو أفضل من هذا ، الأمر الذي يتطلب تكرار نفسك:

if [ -d /path/you/want/to/enter ]; then
    pushd /path/you/want/to/enter
    # commands you want to run in this directory
    popd
fi

نفس الشيء يعمل مع cd و mv و rm وما إلى ذلك ... إذا قمت بتجربتها على ملفات غير موجودة ، فسوف يخرجون بخطأ وطباعة رسالة تقول أنها غير موجودة ، وسوف يتم حجبها. تخطي. إذا قمت بتجربتها على ملفات موجودة بالفعل ، فسيتم تنفيذ الأمر وإنهاء حالة 0 ، مما يتيح لك تنفيذ ذلك.


هنا تعبير براغماتي للغاية:

(cd $dir) || return # is this a directory,
                    # and do we have access?

أنا عادة التفاف في وظيفة:

can_use_as_dir() { 
    (cd ${1:?pathname expected}) || return
}

أو:

assert_dir_access() { 
    (cd ${1:?pathname expected}) || exit
}

الشيء الجميل في هذا النهج هو أنني لست بحاجة إلى التفكير في رسالة خطأ جيدة.

cd سوف تعطيني رسالة خط واحد إلى stderr بالفعل. كما سيقدم المزيد من المعلومات أكثر مما سأستطيع توفيره. عن طريق تنفيذ cd داخل subshell ( ... ) ، لا يؤثر الأمر على الدليل الحالي للمتصل. إذا كان الدليل موجودًا ، فإن هذا المستند الفرعي والدالة هما مجرد إجراء.

التالي هو الوسيطة التي نمررها إلى cd : ${1:?pathname expected} . هذا هو شكل أكثر تفصيلاً لاستبدال المعلمات والذي يتم شرحه بمزيد من التفاصيل أدناه.

Tl؛ dr: إذا كانت السلسلة التي تم تمريرها إلى هذه الدالة فارغة ، فإننا نخرج مرة أخرى من subshell ( ... ) ونرجع من الدالة برسالة خطأ معينة.

نقلا عن صفحة رجل ksh93 :

${parameter:?word}

إذا تم تعيين parameter وهي غير فارغة ، فعليك استبدال قيمتها. خلاف ذلك ، قم بطباعة word والخروج من shell (إن لم يكن تفاعليًا). إذا تم حذف word فستتم طباعة رسالة قياسية.

و

إذا كانت النقطتين : تم حذفها من التعبيرات أعلاه ، فإن shell يقوم فقط بالتحقق من ضبط المعلمة أم لا.

الصياغة هنا غريبة على وثائق shell ، حيث قد تشير word إلى أي سلسلة معقولة ، بما في ذلك المسافات البيضاء.

في هذه الحالة بالذات ، أعلم أن رسالة الخطأ القياسية 1: parameter not set ليست كافية ، لذا أقوم بتكبير نوع القيمة التي نتوقعها هنا - pathname الدليل.

ملاحظة فلسفية: الصدفة ليست لغة موجهة للكائنات ، لذلك تقول الرسالة pathname ، وليس directory . في هذا المستوى ، سأفضل أن أبقيه بسيطًا - الحجج إلى الدالة هي مجرد سلاسل.


وفقا لتعليق :

إذا كنت تريد إنشاء الدليل ولم يكن موجودًا حتى الآن ، فإن الطريقة الأبسط هي استخدام mkdir -p الذي يقوم بإنشاء الدليل - وأي أدلة مفقودة في المسار - ولا يفشل إذا كان الدليل موجودًا بالفعل ، لذا يمكنك افعلها كلها مرة واحدة مع:

mkdir -p /some/directory/you/want/to/exist || exit 1

يقوم الأمر ls بالاقتران مع الخيار -l (الإدراج الطويل) بإرجاع معلومات حول الملفات والدلائل.
على وجه الخصوص ، الحرف الأول ls -l عادة ما يكون d أو - (شرطة). في حالة وجود d هو واحد مدرج هو دليل بالتأكيد.

سوف يخبرك الأمر التالي في سطر واحد فقط ما إذا كان متغير ISDIR المحدد يحتوي على مسار إلى دليل أم لا:

[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
    echo "YES, $ISDIR is a directory." || 
    echo "Sorry, $ISDIR is not a directory"

الاستخدام العملي:

    [[email protected] ~]$ ISDIR="$HOME/Music" 
    [[email protected] ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [[email protected] ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." ||
        echo "Sorry, $ISDIR is not a directory"
    YES, /home/claudio/Music is a directory.

    [[email protected] ~]$ touch "empty file.txt"
    [[email protected] ~]$ ISDIR="$HOME/empty file.txt" 
    [[email protected] ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." || 
        echo "Sorry, $ISDIR is not a directoy"
    Sorry, /home/claudio/empty file.txt is not a directory

[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"

[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

ملاحظة: تعتبر متغيرات الاقتباس ممارسة جيدة.


if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

هذا ليس صحيحًا تمامًا ... إذا كنت تريد الانتقال إلى هذا الدليل ، يجب أن يكون لديك أيضًا حقوق التنفيذ في الدليل. ربما تحتاج إلى حقوق الكتابة كذلك.

الرسل:

if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
    # ... to go to that directory (even if DIRECTORY is a link)
    cd $DIRECTORY
    pwd
fi
if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
    # ... to go to that directory and write something there (even if DIRECTORY is a link)
    cd $DIRECTORY
    touch foobar
fi

if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi




posix