معنى - كيف يمكنني معرفة ما إذا كان الملف العادي غير موجود في Bash؟



bash معنى (12)

أبسط طريقة

FILE=$1
[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"

https://code.i-harness.com

لقد استخدمت البرنامج النصي التالي لمعرفة ما إذا كان الملف موجودًا:

#!/bin/bash

FILE=$1     
if [ -f $FILE ]; then
   echo "File $FILE exists."
else
   echo "File $FILE does not exist."
fi

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

#!/bin/bash

FILE=$1     
if [ $FILE does not exist ]; then
   echo "File $FILE does not exist."
fi

أفضل القيام بما يلي أحادي الخطوط ، في تنسيق متوافق مع shell POSIX :

$ [ -f "/$DIR/$FILE" ] || echo "$FILE NOT FOUND"

$ [ -f "/$DIR/$FILE" ] && echo "$FILE FOUND"

بالنسبة إلى أمرين ، مثلما يمكنني فعله في نص برمجي:

$  [ -f "/$DIR/$FILE" ] || { echo "$FILE NOT FOUND" ; exit 1 ;}

بمجرد أن بدأت في القيام بذلك ، نادراً ما أستخدم تركيب الجملة المكتوب بالكامل!


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

if [ ! -f "$file" ]; then
    echo "$file"
fi

إلى

test -f "$file" || echo "$file"

أو

[ -f "$file" ] || echo "$file"

في

[ -f "$file" ]

[ الأمر هو stat() (غير lstat() ) استدعاء النظام على المسار المخزن في $file وإرجاع true إذا نجح ذلك استدعاء النظام ونوع الملف كما تم إرجاعها بواسطة stat() هو "عادي".

لذا إذا عاد [ -f "$file" ] إلى true ، فيمكنك أن تقول أن الملف موجود وأنه عبارة عن ملف عادي أو رابط يرمز إليه في النهاية إلى ملف عادي (أو على الأقل كان في وقت إصدار stat() ).

ولكن إذا كانت ترجع false (أو إذا كان [ ! -f "$file" ] أو ! [ -f "$file" ] بإرجاع true) ، فهناك العديد من الاحتمالات المختلفة:

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

باختصار ، يجب أن يكون:

if [ -f "$file" ]; then
  printf '"%s" is a path to a regular file or symlink to regular file\n' "$file"
elif [ -e "$file" ]; then
  printf '"%s" exists but is not a regular file\n' "$file"
elif [ -L "$file" ]; then
  printf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not\n' "$file"
else
  printf 'I cannot tell if "%s" exists, let alone whether it is a regular file or not\n' "$file"
fi

لكي نعرف على وجه اليقين أن الملف غير موجود ، سنحتاج إلى استدعاء النظام stat() مع رمز خطأ من ENOENT (يخبرنا ENOTDIR أحد مكونات المسار ليس دليلاً هو حالة أخرى يمكننا فيها معرفة الملف غير موجود في هذا المسار). لسوء الحظ ، لا يسمح لنا الأمر بمعرفة ذلك. سيعود كاذب ما إذا كان رمز الخطأ هو ENOENT أو EACCESS (تم رفض الإذن) أو ENAMETOOLONG أو أي شيء آخر.

يمكن أيضًا إجراء اختبار [ -e "$file" ] باستخدام ls -Ld -- "$file" > /dev/null . في هذه الحالة ، ls سبب فشل stat() ، على الرغم من أن المعلومات لا يمكن استخدامها بسهولة برمجيًا:

$ file=/var/spool/cron/crontabs/root
$ if [ ! -e "$file" ]; then echo does not exist; fi
does not exist
$ if ! ls -Ld -- "$file" > /dev/null; then echo stat failed; fi
ls: cannot access '/var/spool/cron/crontabs/root': Permission denied
stat failed

يقول لي على الأقل أنه ليس بسبب عدم وجود الملف الذي يفشل. لأنه لا يمكنه معرفة ما إذا كان الملف موجودًا أم لا. الأمر [ تجاهل المشكلة فقط.

باستخدام shell zsh ، يمكنك الاستعلام عن رمز الخطأ المتغير الخاص $ERRNO بعد فشل الأمر [ ، وفك ترميز ذلك باستخدام الصفيف الخاص $errnos في الوحدة النمطية zsh/system :

zmodload zsh/system
ERRNO=0
if [ ! -f "$file" ]; then
  err=$ERRNO
  case $errnos[err] in
    ("") echo exists, not a regular file;;
    (ENOENT|ENOTDIR)
       if [ -L "$file" ]; then
         echo broken link
       else
         echo does not exist
       fi;;
    (*) echo "can't tell"; syserror "$err"
  esac
fi

(حذار دعم $errnos مع بعض إصدارات zsh عند إنشاء الإصدارات الأخيرة من gcc ).



لاختبار وجود الملف ، يمكن أن تكون المعلمة أيًا مما يلي:

-e: Returns true if file exists (regular file, directory, or symlink)
-f: Returns true if file exists and is a regular file
-d: Returns true if file exists and is a directory
-h: Returns true if file exists and is a symlink

تنطبق جميع الاختبارات أدناه على الملفات العادية والأدلة والارتباطات الصوتية:

-r: Returns true if file exists and is readable
-w: Returns true if file exists and is writable
-x: Returns true if file exists and is executable
-s: Returns true if file exists and has a size > 0

مثال على النص البرمجي:

#!/bin/bash
FILE=$1

if [ -f "$FILE" ]; then
   echo "File $FILE exists"
else
   echo "File $FILE does not exist"
fi

هذا الرمز يعمل أيضا.

#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
 echo "File '$FILE' Exists"
else
 echo "The File '$FILE' Does Not Exist"
fi

هناك ثلاث طرق مميزة للقيام بذلك:

  1. قم بإلغاء حالة الخروج مع bash (لم يرد أي إجابة أخرى):

    if ! [ -e "$file" ]; then
        echo "file does not exist"
    fi
    

    أو:

    ! [ -e "$file" ] && echo "file does not exist"
    
  2. قم بإبطال الاختبار داخل أمر الاختبار [ (هذه هي الطريقة التي تقدم بها معظم الإجابات قبل تقديمها):

    if [ ! -e "$file" ]; then
        echo "file does not exist"
    fi
    

    أو:

    [ ! -e "$file" ] && echo "file does not exist"
    
  3. التصرف بناءً على نتيجة الاختبار السلبية ( || بدلاً من && ):

    فقط:

    [ -e "$file" ] || echo "file does not exist"
    

    هذا يبدو سخيفًا (IMO) ، لا تستخدمه ما لم يكن رمزك محمولًا إلى غلاف Bourne (مثل /bin/sh لـ Solaris 10 أو ما قبله) التي تفتقر إلى عامل إلغاء خط أنابيب ( ! ):

    if [ -e "$file" ]; then
        :
    else
        echo "file does not exist"
    fi
    

يحتوي الأمر test ( [ هنا] على عامل تشغيل منطقي "غير" وهو نقطة التعجب (على غرار العديد من اللغات الأخرى). جرب هذا:

if [ ! -f /tmp/foo.txt ]; then
    echo "File not found!"
fi

يعمل هذا البرنامج النصي shell أيضاً للبحث عن ملف في دليل:

echo "enter file"

read -r a

if [ -s /home/trainee02/"$a" ]
then
    echo "yes. file is there."
else
    echo "sorry. file is not there."
fi

باش اختبار الملف

-b filename - حظر ملف خاص
-c filename - ملف شخصي خاص
-d directoryname - التحقق من وجود دليل
-e filename - التحقق من وجود الملف ، بغض النظر عن النوع (عقدة ، دليل ، مقبس ، إلخ.)
-f filename - تحقق من وجود ملف عادي وليس دليلاً
-G filename - تحقق من وجود ملف ومملوكة لمجموعة فعالة من الهوية
-G filename set-group-id - صحيح إذا كان الملف موجودا وهو معرف المجموعة المحددة
-k filename - اللزجة
-L filename - ارتباط رمزي
-O filename - صحيح إذا كان الملف موجودا ومملوكة لمعرف المستخدم الفعال
-r filename - تحقق مما إذا كان الملف قابلاً للقراءة
-S filename - تحقق ما إذا كان الملف مأخذ التوصيل
-s filename - تحقق ما إذا كان الملف حجم غير صفري
-u filename - تحقق مما إذا كان قد تم تعيين ملف بت مجموعة المستخدم
-w filename - تأكد من أن الملف قابل للكتابة
-x filename - تحقق مما إذا كان الملف قابل للتنفيذ

كيف تستعمل:

#!/bin/bash
file=./file
if [ -e "$file" ]; then
    echo "File exists"
else 
    echo "File does not exist"
fi 

يمكن إلغاء تعبير اختبار باستخدام ! المشغل أو العامل

#!/bin/bash
file=./file
if [ ! -e "$file" ]; then
    echo "File does not exist"
else 
    echo "File exists"
fi 

[[ -f $FILE ]] || printf '%s does not exist!\n' "$FILE"

من المحتمل أيضًا أن يكون الملف عبارة عن رابط رمزي معطل ، أو ملف غير منتظم ، على سبيل المثال ، مقبس أو جهاز أو جهاز fifo. على سبيل المثال ، لإضافة علامة اختيار للارتباطات symlinks المعطلة:

if [[ ! -f $FILE ]]; then
    if [[ -L $FILE ]]; then
        printf '%s is a broken symlink!\n' "$FILE"
    else
        printf '%s does not exist!\n' "$FILE"
    fi
fi




scripting