سؤال

هل هناك أي طريقة في Linux لحساب عدد الملفات في دليل (أي الأطفال المباشرين) في O (1) (بشكل مستقل عن عدد الملفات) دون الحاجة إلى سرد الدليل أولاً؟ إذا لم يكن O (1) ، هل هناك طريقة فعالة بشكل معقول؟

أنا أبحث عن بديل عن ls | wc -l.

هل كانت مفيدة؟

المحلول

Readdir ليس باهظ الثمن كما تعتقد. يتم تجنب الموهبة في كل ملف ، و (اختياريا) فرز إخراج LS.

/bin/ls -1U | wc -l

يتجنب الأسماء المستعارة في قذيفك ، ولا يقوم بفرز الإخراج ، ويسرد 1 ملف لكل خط (ليس ضروريًا تمامًا عند تنشيط الإخراج إلى WC).

يمكن إعادة صياغة السؤال الأصلي على أنه "هل بنية بيانات أحد الدليل تخزن عددًا من عدد الإدخالات؟" ، والتي لا تكون الإجابة عليها. لا توجد طريقة أكثر كفاءة لحساب الملفات من ReadDir (2)/getDents (2).

نصائح أخرى

يمكن للمرء الحصول على عدد من الدلائل الفرعية في دليل معين دون عبور القائمة بأكملها عن طريق STAT'ing (STAT (1) أو STAT (2)) الدليل المحدد ومراقبة عدد الروابط لهذا الدليل. سيكون للدليل المعطى مع دلائل الطفل عدد ارتباطات N+2 ، رابط واحد لـ ".." إدخال كل دليل فرعي ، بالإضافة إلى اثنين لـ "." و ".." إدخالات الدليل المعطى.

ومع ذلك ، لا يمكن للمرء الحصول على عدد جميع الملفات (سواء كانت الملفات العادية أو الدلائل الفرعية) دون عبور القائمة بأكملها - وهذا صحيح.

لن يحصل أمر "/bin/ls -1u" على جميع الإدخالات. سوف تحصل فقط إدخالات الدليل التي لا تبدأ مع شخصية النقطة (.). على سبيل المثال ، لن يحسب ملف ".profile" الموجود في العديد من الدلائل المنزلية لتسجيل الدخول.

يمكن للمرء استخدام الأمر "/bin/ls -f" أو أمر "/bin/ls -ua" لتجنب النوع والحصول على جميع الإدخالات.

ربما لسوء الحظ لأغراضك ، إما الأمر "/bin/ls -f" أو أمر "/bin/ls -ua" سيحسب أيضًا "." و ".." إدخالات في كل دليل. سيتعين عليك طرح 2 من العدد لتجنب حساب هاتين الإدخالات ، كما في ما يلي:

expr `/bin/ls -f | wc -l` - 2     # Those are back ticks, not single quotes.

خيار-format = العمود الفردي (-1) ليس ضروريًا في الأمر "/bin/ls -ua" عند تنبيه الإخراج "ls" ، كما هو الحال في "WC" في هذه الحالة. سيقوم الأمر "LS" تلقائيًا بكتابة إخراجه في عمود واحد إذا لم يكن الإخراج محطة.

ال -U خيار ل ls ليس في Posix ، وفي OS X's ls لها معنى مختلف من GNU ls, وهو ما يجعله -t و -l استخدم أوقات الخلق بدلاً من أوقات التعديل. -f في Posix كملحق XSI. دليل GNU ls يصف -f كما do not sort, enable -aU, disable -ls --color و -U كما do not sort; list entries in directory order.

يصف Posix -f مثله:

إجبار كل حجة على تفسيرها كدليل وسرد الاسم الموجود في كل فتحة. يجب إيقاف تشغيل هذا الخيار -l, -t, -s, ، و -r, ويجب تشغيله -a; ؛ الترتيب هو الترتيب الذي تظهر فيه الإدخالات في الدليل.

أوامر مثل ls|wc -l إعطاء النتيجة الخاطئة عندما تحتوي أسماء الملفات على الخطوط الجديدة.

في ZSH يمكنك أن تفعل شيئًا كهذا:

a=(*(DN));echo ${#a}

D (glob_dots) يتضمن الملفات التي يبدأ اسمها بفترة و N (null_glob) يتسبب في عدم أن يؤدي الأمر إلى خطأ في دليل فارغ.

أو نفس الشيء في باش:

shopt -s dotglob nullglob;a=(*);echo ${#a[@]}

إذا IFS يحتوي على أرقام ASCII ، أضف عروض أسعار مزدوجة حولها ${#a[@]}. يضيف shopt -u failglob لتتآكد من ذلك failglob غير محدد.

الخيار المحمول هو الاستخدام find:

find . ! -name . -prune|grep -c /

grep -c / يمكن استبداله بـ wc -l إذا كانت أسماء الملفات لا تحتوي على الخطوط الجديدة. ! -name . -prune هو بديل محمول ل -mindepth 1 -maxdepth 1.

أو إليك بديل آخر لا يتضمن عادة ملفات تبدأ اسمها بفترة:

set -- *;[ -e "$1" ]&&echo "$#"

ومع ذلك ، فإن الأمر أعلاه يتضمن الملفات التي يبدأ اسمها بفترة مثل خيار مثل dotglob في باش أو glob_dots في ZSH تم تعيينه. متي * لا يتطابق مع أي ملف ، يؤدي الأمر إلى خطأ في ZSH مع الإعدادات الافتراضية.

لقد استخدمت هذا الأمر .. مثل السحر .. فقط لتغيير maxdepth .. هذا هو الدلائل الفرعية

find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \;

أعتقد أنه يمكنك الحصول على مزيد من التحكم في هذا باستخدام find:

find <path> -maxdepth 1 -type f -printf "." | wc -c
  • find -maxdepth 1 لن يذهب أعمق في التسلسل الهرمي للملفات.
  • -type f يسمح التصفية بالملفات فقط. وبالمثل ، يمكنك استخدام -type d للدلائل.
  • -printf "." يطبع نقطة لكل مباراة.
  • wc -c يحسب الشخصيات ، بحيث يعتبر النقاط التي أنشأتها print... مما يعني حساب عدد الملفات الموجودة في المسار المحدد.

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

للحصول على عدد جميع الملفات في دليل حالي ، حاول هذا:

ls -lR * | wc -l

استخدم LS -1 | WC -L

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top