أنت تخاطر بفقدان البيانات عن طريق استخدام هذا الرمز البديل لنظام Linux بطريقة خاطئة
تتيح لك أحرف البدل في لينكس كتابة أمر واحد يعمل على مجموعات كاملة من الملفات في نفس الوقت. وهذا يوفر الكثير من الوقت، إلا إذا حدث خطأ ما. ويمكن أن يحدث ذلك بشكل مدمر.
ما هي استخدامات البطاقات البرية؟
تعتبر علامة الاستفهام، ?، وعلامة النجمة، * من أشهر أحرف البدل. ويمكن استخدام هذه الأحرف لإنشاء أنماط أسماء الملفات. تمثل علامة الاستفهام أي حرف واحد، وتمثل علامة النجمة أي تسلسل من الأحرف، بما في ذلك الأحرف الصفرية.
بمعرفة ذلك، يمكننا إنشاء أنماط تتوافق مع أسماء ملفات متعددة. فبدلاً من كتابة جميع أسماء الملفات على سطر الأوامر، نقوم بكتابة النمط بدلاً من ذلك. ويتم التعامل مع جميع الملفات التي تتوافق مع النمط بواسطة الأمر.
إذا كان لدينا مجموعة من الملفات في دليل مثل هذا:
يمكننا تحديد مجموعات من الملفات التي تطابق الأنماط التي نقدمها.
ls taf_*
وهذا يعطينا جميع الملفات التي تحتوي على “taf_” في بداية أسمائها.
ls *.sh
ls s*.sh
يسرد الأمر الأول جميع ملفات نصوص shell الموجودة في الدليل. يسرد الأمر الثاني فقط الملفات التي تبدأ بحرف “s” والتي تعد أيضًا ملفات نصوص shell.
يبدو الأمر بسيطًا بما فيه الكفاية، ومع الأمر ls، فهو كذلك بالفعل. ولكن يمكن لأوامر أخرى الاستفادة من هذا النوع من مطابقة الأنماط. تنشأ المشكلات عندما تحاول shell المساعدة من خلال مطابقة الأنماط قبل أن تتاح الفرصة للأمر.
استخدام علامة النجمة مع الأمر find
تسمى عملية توسيع نمط إلى قائمة من الملفات المطابقة غلوبينج.
بدأ الأمر كأمر مستقل في إصدار يونكس 6، ثم أصبح مكتبة يمكن ربطها ببرامج أخرى، والآن أصبح جزءًا مدمجًا في غلاف الأوامر. يتم توسيع النمط بواسطة الغلاف، ويتم تمرير نتائج التوسيع إلى الأمر كمعلمات لسطر الأوامر.
سنلقي نظرة على مثالين باستخدام أمر البحث. الأول يقوم بما قد تتوقعه، ولكن الثاني قد يفاجئك.
في هذا المثال، سنستخدم دليلاً يحتوي على ملف واحد فقط، يسمى readme.txt. يوجد دليلان، src وinc. يحتويان على مزيج من ملفات C وH وMD وTMP.
ls -R
يمكننا استخدام find للعثور بشكل متكرر على الملفات (-type f) ذات الأسماء التي تتطابق مع نمطنا (-name *.c)، مما يمنحنا قائمة بالملفات C.
find . -type f -name *.c
يمكننا إضافة خيار -not لعكس البحث، مما يظهر لنا كل شيء بعيدا الملفات C.
find . -type f -not -name *.c
بعد مراجعة هذه القائمة، قررنا حذف كل شيء باستثناء ملفات C. يمكننا القيام بذلك عن طريق إضافة خيار -delete.
find . -type f -not -name *.c -delete
find .
يقوم الأمر الثاني find بإدراج كل شيء في الدليل الحالي وما تحته بشكل متكرر. كل ما تبقى هو ملفات C الخاصة بنا.
لقد نجحت هذه الطريقة كما توقع معظمنا. الآن سنفعل نفس الشيء تمامًا، ولكن هذه المرة الملف الموجود في الدليل الحالي ليس ملف نصي، بل هو ملف C.
ls -R
سنستخدم نفس أمر البحث والخيارات لحذف كل شيء باستثناء ملفات C. هذا ليس ما كنا نريده على الإطلاق.
find . -type f -not -name *.c -delete
find .
لقد قام هذا بكل بساطة بحذف كل ملف في شجرة الدليل، باستثناء ملف C الموجود في الدليل الحالي.
سنقوم بإعادة تعيين الملفات مرة أخرى، وإصدار الأمر بالطريقة التي نتبعها مفترض لاستخدامه.
تم وضع جميع الملفات في مكانها، ولدينا ملف C في الدليل الحالي، تمامًا كما فعلنا من قبل.
ls -R
هذه المرة، سنقوم بتغليف نمط البطاقة البدل بين علامتي اقتباس مفردتين.
find . -type f -not -name '*.c' -delete
find .
هذا ما أردناه، لقد اختفى كل شيء باستثناء ملفات C الخاصة بنا.
حسنًا، ما الذي حدث خطأً؟
تمنع علامات الاقتباس المفردة shell من توسيع نمط اسم الملف. يتم تمريره إلى الأمر أو البرنامج كما هو، حتى يعمل الأمر عليه.
في المثال الذي نجح، كان لدينا ملف readme.txt في الدليل الحالي. لم يتمكن shell من العثور على تطابق مع *.c، لذا فقد مرر *.c إلى find للعمل عليه.
في المثال الذي حذف كل شيء باستثناء ملفات C، كان لدينا ملف يسمى main.c في الدليل الحالي. تطابقت shell مع النمط لهذا الملف، ومرت اسم الملف إلى أمر find. لذا كانت تعليمات find هي حذف كل شيء لم يُسمى main.c.
يمكننا توضيح ذلك باستخدام برنامج C صغير لا يفعل أكثر من عرض معلمات سطر الأوامر في نافذة المحطة الطرفية.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv())
{
int i;
printf(“You supplied %d arguments.\n”, argc-1);
for (i=1; i printf(“%-2d) \”%s\”\n”, i, argv(i));
exit (0);
}
لقد قمت بحفظ هذا كملف يسمى glob.c، وقمت بتجميعه باستخدام:
gcc -o glob glob.c
يحتوي المتغير argc على عدد الوسائط التي نمررها إلى البرنامج. تمر حلقة for عبر قائمة الوسائط وتطبع كل واحدة منها في نافذة المحطة الطرفية.
تبدأ حلقة for عند الحجة الأولى، وليس الصفر. هناك حجة صفرية. وهي تحمل دائمًا اسم الثنائي نفسه. لتجنب تعقيد الأمور، تجنبت طباعتها. الحجات الوحيدة التي تتم طباعتها هي تلك التي نوفرها على سطر الأوامر.
./glob one two 3 ant beetle cockroach
دعنا نحاول ذلك باستخدام *.c كمعلمة لسطر الأوامر.
ls *.c
./glob *.c
في حالة عدم وجود أي ملفات C في الدليل الحالي، يقوم shell بتمرير *.c إلى أمر find. ثم يعمل أمر find على نمط الأحرف البدل نفسه. ولكن عندما يكون لدينا ملف C في الدليل الحالي، يقوم shell بتمرير اسم ملف C المطابق إلى البرنامج.
ls *.c
./glob *.c
يتلقى برنامجنا اسم ملف C كمعامل له، وينطبق الأمر نفسه على أمر find. لذا، في الواقع، كان الأمر find يقوم بما قيل له أن يفعله: حذف جميع الملفات باستثناء ملف main.c.
هذه المرة، سنقوم بتغليف نمط البطاقة البدل بين علامتي اقتباس مفردتين.
ls *.c
./glob ‘*.c’
تتجاهل القشرة فرصة تطبيق تأثيرها على نمط البطاقة البدل، وتمررها مباشرة إلى الأمر لمزيد من المعالجة.
إصلاح بسيط، يمكنك اقتباسي
كقاعدة عامة، اقتبس أنماط الأحرف البدل التي تمررها إلى الأوامر مثل find. هذا كل ما يلزم لمنع هذا النوع من الحوادث الكارثية المحتملة.