لفرز الملفات الموجودة في المستوى الأعلى من التنزيلات إلى مجلدات حسب امتدادها، استخدم نصًا برمجيًا يفحص الملفات الموجودة مباشرةً، وينشئ مجلدات مثل txt وcsv، ويتجاوز أسماء الوجهات الموجودة مسبقًا. ابدأ بالمثال المؤقت أدناه، وعاين عمليات النقل، ثم شغّله من Terminal أو اختصارات Apple.
هذا الدليل مخصص لمستخدم Mac يريد نقل الملفات المنفردة فعليًا إلى مجلدات، مع ترك المجلدات الفرعية الموجودة ومحتوياتها كما هي. أداة اتخاذ القرار الأساسية فيه هي تقرير معاينة: يظهر لكل ملف مؤهل مسار الوجهة المقترح، بينما تُعرض رسالة واضحة عند تجاوز التصادمات والأسماء غير المدعومة.
ما الذي سيُنقل، وما الذي سيبقى في مكانه؟
يوفر Finder عناصر تحكم للفرز والتجميع، إلى جانب المجلدات والمجلدات الذكية. توضح Apple أن المجلد الذكي يعرض الملفات المطابقة معًا من دون نقلها. أما في هذه المهمة، فالنتيجة المطلوبة هي مجلدات فعلية حسب الامتداد تحتوي على الملفات المنقولة. تنظيم الملفات في Finder على Mac.
قبل فحص المثال، افتح Finder واختر Finder > الإعدادات > متقدم، ثم حدد إظهار كل امتدادات أسماء الملفات. بذلك ستظهر اللواحق التي يستخدمها برنامج الفرز. لا يؤدي إظهار الامتداد إلى تغيير تنسيق الملف. إظهار امتدادات أسماء الملفات أو إخفاؤها على Mac.
يستخدم النص البرمجي أدناه القواعد المقصودة التالية. وهي تصف هذا التنفيذ، ولا تمثل سلوكًا عامًا لـ Finder أو الاختصارات:
| العنصر الذي تتم مواجهته | سلوك برنامج الفرز |
|---|---|
ملف عادي موجود مباشرةً، مثل note.TXT |
يقترح txt/note.TXT؛ ويحافظ على اسم الملف الأصلي |
اسم مركب مثل bundle.tar.gz |
يستخدم اللاحقة الأخيرة: gz/bundle.tar.gz |
| ملف بلا نقطة، أو ينتهي اسمه بنقطة | يتركه في مكانه ويعرض رسالة بالتجاوز |
| مجلد، بما في ذلك مجلد يحمل اسمًا بامتداد | يتركه ومحتوياته في مكانها |
| اسم يبدأ بنقطة | يستبعده من الفحص |
| رابط رمزي | يتركه في مكانه |
| امتداد يحتوي على أي شيء غير الأحرف والأرقام اللاتينية ASCII، أو يزيد طوله على 32 حرفًا | يترك الملف في مكانه ويعرض رسالة بالتجاوز |
| وجهة موجودة تحمل اسم الملف نفسه | يترك المصدر في مكانه ويعرض رسالة عن التصادم |
| اسم مجلد الوجهة مشغول بملف عادي أو رابط رمزي | يعرض رسالة تفيد بتعذر إنشاء المجلد ويترك المصدر في مكانه |
تحافظ قيود الامتداد على بساطة قاعدة تسمية المجلدات وسهولة توقعها. ويظل الملف الذي تم تجاوزه متاحًا لاتخاذ قرار يدوي؛ فلا يخترع النص البرمجي اسمًا بديلًا ولا يحذفه بصمت.
إنشاء مثال مؤقت لمجلد التنزيلات
افتح Terminal والصق كتلة الإعداد الكاملة التالية. فهي تنشئ ملفات نصية اصطناعية فقط داخل Downloads/ExtensionSortDemo. لبعضها امتدادات توضيحية مثل .gz؛ لكن محتوياتها نصوص نموذجية عادية وليست أمثلة على تلك التنسيقات. يتوقف الإعداد إذا كان مجلد العرض التوضيحي موجودًا بالفعل، لذلك لن تؤدي إعادة تشغيله إلى إعادة ضبط اختبار سابق.
توثق Apple استخدام Terminal لتنفيذ الأوامر والنصوص البرمجية، وتوثق الأمر mv لنقل الملفات المحلية. هنا، يوفر Terminal طريقة سهلة القراءة لمعاينة كل عملية نقل مخططة قبل تنفيذها. ما هو Terminal على Mac؟، إدارة الملفات في Terminal على Mac.
/bin/bash <<'BASH'
set -eu
demo="$HOME/Downloads/ExtensionSortDemo"
/bin/mkdir "$demo"
/bin/mkdir "$demo/nested" "$demo/txt"
printf 'sample text\n' > "$demo/sample.txt"
printf 'uppercase suffix example\n' > "$demo/note.TXT"
printf 'name,value\nblue,1\n' > "$demo/palette.csv"
printf 'synthetic compound-name example\n' > "$demo/bundle.tar.gz"
printf 'no extension example\n' > "$demo/README"
printf 'trailing dot example\n' > "$demo/trailing."
printf 'hidden example\n' > "$demo/.hidden.txt"
printf 'nested example\n' > "$demo/nested/inside.txt"
printf 'existing destination example\n' > "$demo/txt/sample.txt"
printf 'blocks creation of a csv folder\n' > "$demo/csv"
printf 'Created demo folder: %s\n' "$demo"
BASH
افتح التنزيلات في Finder، ثم افتح ExtensionSortDemo. لاحظ وجود ملفين مختلفين باسم sample.txt: أحدهما في المستوى الأعلى للمجلد التجريبي، والآخر موجود مسبقًا داخل txt. ولاحظ أيضًا أن csv ملف. هذه اختبارات مقصودة لسببين شائعين لتجاوز عملية النقل.
معاينة برنامج الفرز قبل نقل الملفات
الصق البرنامج الكامل أدناه في Terminal. إعدادُه الأولي هو mode=preview، لذا يعرض عمليات النقل المقترحة من دون إنشاء مجلدات للامتدادات أو نقل الملفات. المسار الجذر المحدد هو مجلد العرض التوضيحي المؤقت، وليس مجلد التنزيلات بأكمله.
/bin/bash <<'BASH'
set -u
export LC_ALL=C
unset GLOBIGNORE
shopt -s nullglob
shopt -u dotglob
root="$HOME/Downloads/ExtensionSortDemo"
mode=preview
case "$mode" in
preview|move) ;;
*) printf 'Invalid mode\n' >&2; exit 1 ;;
esac
if [ ! -d "$root" ] || [ -L "$root" ]; then
printf 'Root must be an existing ordinary folder\n' >&2
exit 1
fi
for file in "$root"/*; do
if [ -L "$file" ] || [ ! -f "$file" ]; then
printf 'SKIP non-regular: %q\n' "$file"
continue
fi
name=${file##*/}
case "$name" in
*.*) ext=${name##*.} ;;
*) printf 'SKIP no extension: %q\n' "$name"; continue ;;
esac
case "$ext" in
''|*[!A-Za-z0-9]*)
printf 'SKIP unsupported extension: %q\n' "$name"
continue ;;
esac
if [ "${#ext}" -gt 32 ]; then
printf 'SKIP long extension: %q\n' "$name"
continue
fi
ext=$(printf '%s' "$ext" | /usr/bin/tr '[:upper:]' '[:lower:]')
folder="$root/$ext"
dest="$folder/$name"
if [ -L "$folder" ] || { [ -e "$folder" ] && [ ! -d "$folder" ]; }; then
printf 'SKIP blocked folder: %q\n' "$folder"
continue
fi
if [ -e "$dest" ] || [ -L "$dest" ]; then
printf 'SKIP collision: %q\n' "$dest"
continue
fi
if [ "$mode" = preview ]; then
printf 'WOULD MOVE %q -> %q\n' "$file" "$dest"
continue
fi
/bin/mkdir -p "$folder" || exit 1
/bin/mv -n "$file" "$dest" || exit 1
if [ -e "$file" ] || [ -L "$file" ]; then
printf 'NOT MOVED: %q\n' "$file" >&2
exit 1
fi
printf 'MOVED %q -> %q\n' "$file" "$dest"
done
printf 'Finished (%s). Review all SKIP lines.\n' "$mode"
BASH
لا يتعمق النمط \"$root\"/* في المجلدات. ثم تستبعد فحوصات الملفات المجلدات والروابط الرمزية. يعالج nullglob المجلد الفارغ من دون اعتبار النمط غير المطابق اسمًا لملف؛ كما أن تعطيل dotglob يستبعد الأسماء التي تبدأ بنقطة. وتوثق هذه السلوكيات في دليل Bash الموزع من Apple. دليل Bash.
يستخرج النص البرمجي اللاحقة الأخيرة ويحوّل أحرفها إلى أحرف لاتينية صغيرة باستخدام tr. لذلك يحتفظ note.TXT باسمه، لكنه ينتقل إلى txt. ويوثق دليل tr من Apple تحويل الأحرف الكبيرة إلى صغيرة المستخدم هنا. tr(1) — تحويل الأحرف.
في هذه العينة، النتائج المتوقعة المهمة هي:
| المصدر الاصطناعي | نتيجة المعاينة المتوقعة |
|---|---|
note.TXT |
سيُنقل إلى txt/note.TXT |
bundle.tar.gz |
سيُنقل إلى gz/bundle.tar.gz |
sample.txt |
تصادم مع txt/sample.txt؛ تجاوز |
palette.csv |
اسم المجلد csv مشغول بملف؛ تجاوز |
README |
بلا امتداد؛ تجاوز |
trailing. |
امتداد فارغ؛ تجاوز |
nested/inside.txt |
لن يُفحص مطلقًا |
.hidden.txt |
لن يُفحص مطلقًا |
هذه نتائج متوقعة لنظام الملفات، وليست ادعاءً بأن عمليات النقل نُفذت أثناء الإعداد. اجتاز البرنامج فحص صياغة Bash، وأكد فحص مستقل وحتمي لتحويل أسماء الملفات استخراج اللاحقة وتحويلها إلى أحرف صغيرة. كانت بيئة الإعداد للقراءة فقط، لذلك لم يُنفذ سير عمل النقل الكامل على macOS.
نقل ملفات المثال والتحقق من النتيجة
بعد أن تطابق المعاينة الجدول، الصق البرنامج الكامل نفسه مرة أخرى بعد تغيير mode=preview فقط إلى mode=move. اترك مسار المجلد التجريبي كما هو لهذا الاختبار.
في وضع النقل، ينشئ mkdir -p المجلد المطلوب أو يقبل مجلدًا موجودًا. لكنه لا يحوّل ملفًا عاديًا موجودًا إلى مجلد، ولهذا يتحقق النص البرمجي من مجلد الوجهة أولًا. mkdir(1) — إنشاء المجلدات.
تستخدم عملية النقل الأمر mv -n في macOS، وسلوكه الموثق هو تجنب الكتابة فوق ملف موجود. يوفر فحص الوجود السابق رسالة واضحة عن التصادم؛ كما أن فحص المصدر اللاحق يلتقط حالة بقاء المصدر بعد محاولة النقل. ويتوقف البرنامج عند الإبلاغ عن فشل أحد الأوامر. mv(1) — نقل الملفات.
افحص المجلد التجريبي في Finder. ينبغي أن تجد note.TXT داخل txt، وأن تجد bundle.tar.gz داخل مجلد gz أُنشئ حديثًا. ينبغي أن تظل نسختا sample.txt في موقعيهما الأصليين. وينبغي أن يبقى palette.csv في المستوى الأعلى، وأن يبقى nested/inside.txt داخل nested.
يعني السطر الأخير Finished أن الفحص اكتمل؛ راجع أيضًا رسائل التجاوز. ينبغي أن تترك إعادة تشغيل برنامج الفرز الملفات المصنفة بالفعل داخل مجلداتها، لأن هذه المجلدات لا تُفحص تكراريًا.
تشغيل برنامج الفرز نفسه من اختصارات Apple
يمكن أن تكون الاختصارات زرًا لتشغيل هذا النص البرمجي. توثق Apple الدعم المضمن لكتابة النصوص البرمجية للصدفة وتشغيلها في محرر الاختصارات. ينفذ البرنامج ربط الامتدادات وفحوصات الوجود؛ ولا تفترض هذه المقالة أن إجراءً أصليًا لنقل الملفات يتصرف بالطريقة نفسها عند حدوث تصادم. التعرّف على الاختصارات لنظام macOS.
أنشئ الاختصار يدويًا وأبقِه موجهًا إلى المجلد التجريبي أثناء الاختبار:
- افتح الاختصارات، وانقر زر الإضافة، وسمّ الاختصار
Sort Extension Demo. - ابحث في قائمة الإجراءات عن
Run Shell Scriptوأضف هذا الإجراء. - اضبط الصدفة على
/bin/bash. الصق كتلة الفرز الكاملة أعلاه، بما فيها السطر الافتتاحي/bin/bashوالفاصل الختاميBASH، في حقل النص البرمجي. اتركmode=previewكما هو في البداية. - أضف
Quick Lookبعد إجراء النص البرمجي، وصِله بمخرجات النص البرمجي. - شغّل الاختصار وافحص تقرير المعاينة قبل تغيير النص البرمجي إلى
mode=move.
توثق Apple إنشاء اختصار بإضافة الإجراءات واختبارها، وتوصي باستخدام Quick Look لفحص المحتوى الذي تنتقل بين الإجراءات. إنشاء اختصار مخصص على Mac، اختبار إجراءاتك في الاختصارات على Mac.
لا يتطلب هذا الاختصار ملفات واردة؛ فالمسار الجذر محدد داخل النص البرمجي. ومخرجاته الناجحة تقرير نصي يعرضه Quick Look. وهذا التقرير ليس مجموعة من كائنات الملفات المنقولة لتمريرها إلى إجراء ملفات آخر. لفحص المدخلات التي يقبلها إجراء ما ومخرجاته في الإصدار المثبت لديك، انقر مع الضغط على Control على أيقونته واختر Show Info، كما توثق Apple. التنقل في قائمة الإجراءات في الاختصارات على Mac.
إذا كانت الاختصارات تتطلب تمكين تنفيذ النصوص البرمجية، فالإعداد الموثق من Apple هو Shortcuts > Settings > Advanced > Allow Running Scripts. إذا لم يكن إجراء الصدفة متاحًا في تثبيتك، فاستخدم برنامج Terminal الكامل أعلاه؛ فهو ينفذ مهمة الفرز نفسها بصورة مستقلة. إعدادات الخصوصية والأمان المتقدمة في الاختصارات على Mac.
تطبيق القاعدة على المستوى الأعلى لمجلد التنزيلات
بعد الاختبار المؤقت، يكون التغيير اللازم في الإعداد لمجلد التنزيلات الفعلي هو استبدال السطر المفرد التالي داخل برنامج الفرز. هذا مقطع إعداد، وليس برنامج فرز مستقلًا:
root="$HOME/Downloads"
ارجع إلى mode=preview كلما غيّرت المسار الجذر. راجع كل وجهة مقترحة ورسالة تجاوز قبل تمكين النقل. يعالج البرنامج الملفات المباشرة المؤهلة دفعة واحدة؛ ولا يوفر مطالبة لاختيار الملفات واحدًا تلو الآخر.
استخدمه كعملية دفعية تبدأها يدويًا على مجلد اكتمل وصول ملفاته. لا يحدد النص البرمجي اكتمال التنزيلات، ولا يراقب الإضافات المستقبلية، ولا ينسق عمليات التشغيل المتزامنة. فحوصاته وعملية النقل عمليتان منفصلتان، لذا أبعد أنشطة نقل الملفات الأخرى عن المجلد أثناء تشغيله. المعاينة تقرير عن الحالة الراهنة، وليست حجزًا للوجهات.
عند حدوث تصادم، افحص الملفين في Finder وقرر ما إذا كنت ستعيد تسمية الملف الموجود في المستوى الأعلى أم ستتركه في مكانه. وإذا كان مجلد امتداد مشغولًا، فتعامل مع العنصر الذي يشغل هذا الاسم قبل إعادة التشغيل. لا تستدعي أي من الحالتين تعديل البرنامج ليكتب فوق الملفات.
أكمل العمل بفحص مجلدات الوجهة الفعلية في Finder ومراجعة أي ملفات متبقية في المستوى الأعلى ومقارنتها بالتقرير. يوفر المثال المؤقت اختبار قبول ملموسًا: تُنقل الملفات المقصودة، وتظل الأسماء الموجودة سليمة، وتبقى محتويات المجلدات المتداخلة في أماكنها الأصلية.
المصادر
- تنظيم الملفات في Finder على Mac — دعم Apple.
- إظهار امتدادات أسماء الملفات أو إخفاؤها على Mac — دعم Apple.
- ما هو Terminal على Mac؟ — دعم Apple.
- إدارة الملفات في Terminal على Mac — دعم Apple.
- دليل Bash — توزيعات Apple للبرامج مفتوحة المصدر.
- tr(1) — تحويل الأحرف — توزيعات Apple للبرامج مفتوحة المصدر.
- mkdir(1) — إنشاء المجلدات — توزيعات Apple للبرامج مفتوحة المصدر.
- mv(1) — نقل الملفات — توزيعات Apple للبرامج مفتوحة المصدر.
- التعرّف على الاختصارات لنظام macOS — مطورو Apple.
- إنشاء اختصار مخصص على Mac — دعم Apple.
- اختبار إجراءاتك في الاختصارات على Mac — دعم Apple.
- التنقل في قائمة الإجراءات في الاختصارات على Mac — دعم Apple.
- إعدادات الخصوصية والأمان المتقدمة في الاختصارات على Mac — دعم Apple.