لنقل الملفات ذات الأسماء المكررة مع الاحتفاظ بالنسختين، امنح كل ملف وارد اسمًا غير مستخدم في الوجهة قبل نقله. ينشئ هذا الدليل اختصارًا على Mac يضيف لواحق مرقمة، باستخدام ملفات نصية مؤقتة لعرض النتيجة.
تتمثل المهمة في نقل ملفات عادية من مجلد محلي إلى مجلد آخر قد يحتوي بالفعل على ملفات تحمل الأسماء نفسها. تظل الملفات الموجودة في الوجهة كما هي؛ وتحصل الملفات الواردة على أسماء مثل notes (2).txt. يعني الاحتفاظ بالنسختين بقاء الملفين في الوجهة بعد النقل، فلا يبقى الملف الوارد في مجلده المصدر.
ما الذي توثقه Apple بشأن الاحتفاظ بالملفين؟
توثّق Apple إمكانية تشغيل نصوص الصدفة مباشرةً داخل تطبيق الاختصارات. ولا تحدد صفحات الاختصارات العامة التي يستشهد بها هذا الدليل سياسة تعارض باسم Keep Both لإجراء Move File. وبدلًا من الاعتماد على إعداد غير موثق، يحدد هذا الإجراء الاسم صراحةً ضمن Run Shell Script. تصف Apple إمكانية البرمجة النصية في التعرّف على الاختصارات لنظام macOS.
لأمر macOS الأساسي سلوك موثق أضيق نطاقًا: يمنع mv -n الكتابة فوق ملف موجود. لكنه لا ينشئ اسمًا جديدًا. لذلك يحتاج هذا الاختصار إلى حلقة لاختيار اسم الملف وإلى خيار منع الكتابة فوق الملفات. وهاتان مهمتان منفصلتان، كما يبيّن مصدر دليل Apple المنشور mv(1).
كذلك، لدمج المجلدات في Finder قيود. تقول Apple إن خيار Merge لا يظهر إلا عندما يحتوي أحد المجلدين على عناصر غير موجودة في الآخر؛ أما إذا احتوى المجلدان على إصدارات مختلفة من ملفات تحمل الأسماء نفسها، فيظهر الخياران Stop وReplace. لذلك لا يوفر دمج المجلدات سلوك الترقيم المطلوب هنا. راجع تنظيم الملفات في مجلدات على Mac.
إعداد مثال مؤقت لأسماء مكررة
استخدم هذا المثال مع مجلدين على القرص المحلي نفسه. يعالج الملفات العادية غير المخفية الموجودة مباشرةً داخل المجلد المصدر. ولا يعالج المجلدات الفرعية تكراريًا، ولا ينقل الأسماء المستعارة أو الروابط الرمزية، ولا يدمج الحزم. شغّل نسخة واحدة في كل مرة، مع التأكد من عدم تغيير أي من المجلدين بواسطة عملية أخرى.
يتطلب الاختصار توفر إجراء Run Shell Script وإمكانية تشغيله على Mac. إذا تعذّر تشغيل هذا الإجراء في إعدادك، فاستخدم طريقة Finder الواردة لاحقًا في هذه المقالة. لا تتطلب الأمثلة أدناه أي برامج إضافية.
افتح Terminal والصق أمر الإعداد الكامل هذا. ينشئ الأمر مجلدًا جديدًا على سطح المكتب يحتوي على نصوص اصطناعية فقط. إذا كان المجلد Shortcuts-name-demo موجودًا بالفعل، فسيتوقف الأمر بدلًا من إعادة استخدام محتوياته.
/bin/bash <<'BASH'
set -e
root="$HOME/Desktop/Shortcuts-name-demo"
/bin/mkdir "$root"
/bin/mkdir "$root/Incoming" "$root/Collected"
printf '%s\n' 'Incoming synthetic notes.' > "$root/Incoming/notes.txt"
printf '%s\n' 'Existing synthetic notes.' > "$root/Collected/notes.txt"
printf '%s\n' 'Earlier synthetic second copy.' > "$root/Collected/notes (2).txt"
printf '%s\n' 'Synthetic readme.' > "$root/Incoming/readme.txt"
printf 'Example folder: %s\n' "$root"
BASH
التعارض مقصود: تحتوي الوجهة بالفعل على كل من notes.txt وnotes (2).txt. وسيواجه اختصار يضيف (2) فقط تعارضًا آخر. والقاعدة العملية هي اختبار الأسماء المرشحة بالتتابع حتى يتوفر اسم غير مستخدم.
لتسهيل الفحص، فعّل Show all filename extensions ضمن Finder > Settings > Advanced. توضح Apple أن إخفاء الامتداد يغيّر طريقة عرضه، بينما يمكن لتغيير الامتداد نفسه التأثير في التطبيق الذي يفتح الملف. أبقِ .txt كما هو في هذا المثال. راجع إظهار امتدادات أسماء الملفات أو إخفاؤها على Mac.
إنشاء الاختصار مع معالجة صريحة للتعارض
أنشئ اختصارًا باستخدام زر الإضافة في تطبيق الاختصارات وسمّه Move Files and Keep Both. ابحث عن Run Shell Script في مكتبة الإجراءات وأضِفه. توثّق Apple إنشاء الاختصارات وإضافة الإجراءات في إنشاء اختصار مخصص على Mac.
اضبط صدفة الإجراء على /bin/bash، ثم استبدل النص البرمجي النموذجي بالبرنامج الكامل أدناه. يقرأ هذا الإصدار مساري المجلدين من متغيرات في النص البرمجي. ولا يستهلك مدخلات الاختصار أو عناصر Finder المحددة أو الإدخال القياسي، لذا لا يؤثر إعداد تمرير الإدخال.
set -e
shopt -s nullglob
src_dir="$HOME/Desktop/Shortcuts-name-demo/Incoming"
dst_dir="$HOME/Desktop/Shortcuts-name-demo/Collected"
fail() {
printf '%s\n' "$1" >&2
exit 1
}
[[ -d "$src_dir" ]] || fail "Source folder does not exist."
[[ -d "$dst_dir" ]] || fail "Destination folder does not exist."
src_dir=$(cd "$src_dir" && pwd -P)
dst_dir=$(cd "$dst_dir" && pwd -P)
[[ "$src_dir" != "$dst_dir" ]] || fail "Choose different folders."
moved=0
for src in "$src_dir"/*; do
if [[ -L "$src" || ! -f "$src" ]]; then
printf 'Skipped non-regular item: %s\n' "$src" >&2
continue
fi
name=${src##*/}
stem=$name
ext=
if [[ "$name" == *.* && "$name" != .* && "$name" != *. ]]; then
stem=${name%.*}
ext=.${name##*.}
fi
target="$dst_dir/$name"
number=2
while [[ -e "$target" || -L "$target" ]]; do
target="$dst_dir/$stem ($number)$ext"
number=$((number + 1))
done
/bin/mv -n "$src" "$target" || fail "Move failed: $src"
if [[ -e "$src" || -L "$src" || ! -f "$target" ]]; then
fail "Move was not completed as expected: $src"
fi
moved=$((moved + 1))
printf 'Moved: %s -> %s\n' "$name" "${target##*/}"
done
printf 'Completed: %s file(s) moved.\n' "$moved"
أضف Quick Look بعد إجراء النص البرمجي لفحص تقريره. توصي Apple تحديدًا بإدراج Quick Look أثناء الاختبار لمعرفة المحتوى الذي ينتقل بين الإجراءات. راجع اختبار الإجراءات في تطبيق الاختصارات على Mac.
يحتوي التقرير على نص يصف عمليات النقل المكتملة. لكنه ليس قائمة بعناصر File المنقولة. إذا وسّعت الاختصار لاحقًا، فلا تتعامل مع سطور التقرير على أنها مدخلات ملفات. توثّق Apple أن الإجراءات تقبل أنواعًا معينة من المحتوى وتنتجها؛ استخدم Show Info على أحد الإجراءات لفحص المدخلات التي يقبلها والمخرجات الناتجة عنه. راجع توصيل الإجراءات في تطبيق الاختصارات على Mac.
كيف تحافظ قاعدة التسمية على النسختين؟
يفحص النص البرمجي أولًا مسار الوجهة الأصلي لكل ملف مصدر. إذا كان المسار مشغولًا، يجرّب (2)، ثم (3)، ويواصل حتى يعثر على اسم مرشح غير مستخدم. وتُعد المجلدات والروابط الرمزية الموجودة مسبقًا أسماءً مشغولة أيضًا. وتستخدم عملية النقل النهائية mv -n كفحص إضافي لمنع الكتابة فوق الملفات، وفقًا لوثائق Apple mv(1).
| الملف الوارد | ما تحتويه الوجهة بالفعل | اسم الوجهة المختار |
|---|---|---|
notes.txt |
لا يوجد عنصر بهذا الاسم | notes.txt |
notes.txt |
notes.txt |
notes (2).txt |
notes.txt |
notes.txt، notes (2).txt |
notes (3).txt |
readme |
readme |
readme (2) |
archive.tar.gz |
archive.tar.gz |
archive.tar (2).gz |
هذه قواعد التسمية التي يتبعها البرنامج، وليست ادعاءً بشأن التسمية التلقائية في Finder. يُفصل الامتداد الأخير فقط: يبقى .gz في نهاية archive.tar (2).gz. ويحتفظ الملف الوارد الذي اسمه notes (2).txt بهذا الاسم الأساسي، لينتج notes (2) (2).txt عند الحاجة. ولا يفسر النص البرمجي رقمًا موجودًا مسبقًا على أنه إصدار.
يضع البرنامج المسارات بين علامتي اقتباس، ويتعامل مع أسماء الملفات الموسّعة بواسطة الصدفة بدلًا من تقسيم قائمة نصية. لذلك تظل الأسماء التي تحتوي على مسافات عناصر مفردة. ويستخدم بناء الجملة Bash عمدًا؛ لذا أبقِ /bin/bash محددًا. يشرح أساسيات نصوص الصدفة من Apple أهمية الاختلافات بين لهجات الصدفة.
تشغيل المثال والتحقق من النتيجة
شغّل الاختصار مرة واحدة، ثم افحص المجلدين في Finder. وبالنسبة إلى البيانات الاصطناعية المقدمة، يُتوقع أن تحتوي الوجهة على ما يلي:
notes.txt، ولا يزال يحتوي علىExisting synthetic notes.notes (2).txt، ولا يزال يحتوي علىEarlier synthetic second copy.notes (3).txt، ويحتوي علىIncoming synthetic notes.readme.txt، ويحتوي علىSynthetic readme.
من المفترض أن يصبح مجلد Incoming فارغًا، وأن ينتهي التقرير بعبارة Completed: 2 file(s) moved.. إذا شغّلت الاختصار مرة أخرى من دون إضافة ملفات، فمن المفترض أن يشير التقرير إلى عدم إجراء أي عمليات نقل. هذه هي النتائج المتوقعة للمثال؛ ولم يُشغّل سير عمل macOS Shortcuts كاملًا أثناء إعداد هذه المقالة. وقد جرى التحقق بشكل منفصل من تعبيرات تقسيم أسماء الملفات باستخدام أسماء اصطناعية.
إذا توقف الاختصار، افحص المجلدين قبل إعادة تشغيله. يُنقل كل ملف على حدة، لذا لا يؤدي حدوث خطأ مع ملف لاحق إلى التراجع عن عمليات النقل السابقة. ويفحص النص البرمجي ما إذا كان الملف لا يزال في المصدر بعد كل أمر، بدلًا من افتراض أن اكتمال أي أمر يعني نقل الملف.
عند حدوث فشل عادي في النقل، توصي Apple بالتحقق مما إذا كان الملف مفتوحًا وما إذا كانت المساحة المتاحة في الوجهة كافية. راجع إذا تعذّر نقل عنصر أو نسخه على Mac. وقد يمنع طول اسم الملف، بعد إضافة لاحقة إليه، هذا البرنامج من إكمال نقله أيضًا؛ إذ يتوقف بدلًا من اقتطاع الاسم.
يحدث فحص وجود الاسم وعملية النقل في خطوتين منفصلتين. صُمم هذا البرنامج لسير عمل محلي واحد يُشغّل يدويًا، مع مجلدات مستقرة. ولا يحجز الأسماء المرشحة ضد التغييرات المتزامنة. أبقِ عمليات التشغيل المتزامنة والعمليات الأخرى التي تكتب في مجلدات المثال خارجها.
استخدام Finder عند وجود عدد قليل من حالات التعارض
إذا كانت الدفعة صغيرة، فأعِد تسمية الملف الوارد صراحةً قبل نقله. في المثال الاصطناعي، افحص Collected، وحدد Incoming/notes.txt، واضغط على Return، وأدخل notes (3).txt، ثم اضغط على Return مرة أخرى. توثّق Apple إجراء إعادة التسمية هذا في إعادة تسمية الملفات والمجلدات والأقراص على Mac.
بعد ذلك، اسحب الملف الذي أعدت تسميته إلى Collected على القرص نفسه. توثّق Apple أن سحب عنصر إلى مجلد ينقله، وأن الضغط باستمرار على Option ينسخه، وأن الضغط باستمرار على Command أثناء السحب إلى قرص آخر ينقله. راجع تنظيم الملفات في مجلدات على Mac. إذا ظهر تعارض آخر في الأسماء، فألغِ النقل واختر اسمًا آخر غير مستخدم.
بعد أن يعمل المثال المؤقت كما هو متوقع على Mac، غيّر فقط src_dir وdst_dir ليتناسبا مع زوج آخر من المجلدات المحلية التي تنطبق عليها الشروط نفسها. أبقِ حلقة الأسماء المرقمة معًا وفحوصات الإكمال: يضمن اختيار اسم غير مستخدم الاحتفاظ بنسختي الوجهة، بينما يوضح فحص النتيجة ما إذا كان الملف الوارد قد نُقل فعلًا.
المصادر
- التعرّف على الاختصارات لنظام macOS — Apple Developer.
- مصدر دليل mv(1) — Apple Open Source Distributions.
- تنظيم الملفات في مجلدات على Mac — Apple Support.
- إظهار امتدادات أسماء الملفات أو إخفاؤها على Mac — Apple Support.
- إنشاء اختصار مخصص على Mac — Apple Support.
- اختبار الإجراءات في تطبيق الاختصارات على Mac — Apple Support.
- توصيل الإجراءات في تطبيق الاختصارات على Mac — Apple Support.
- أساسيات نصوص الصدفة — Apple Developer.
- إذا تعذّر نقل عنصر أو نسخه على Mac — Apple Support.
- إعادة تسمية الملفات والمجلدات والأقراص على Mac — Apple Support.