این مقاله برخی از موارد غیر واضح مربوط به استفاده از آن را نشان می دهد کارت های وحشی هنگام کپی کردن، رفتار دستور مبهم cp هنگام کپی کردن، و همچنین روش هایی که به شما امکان می دهد تعداد زیادی فایل را بدون پرش یا خراب شدن به درستی کپی کنید.
فرض کنید باید همه چیز را از پوشه /source به پوشه /target کپی کنیم.
اولین چیزی که به ذهن می رسد این است:
cp /source/* /target
بیایید بلافاصله این دستور را به صورت زیر اصلاح کنیم:
cp -a /source/* /target
کلید -a کپی از تمام ویژگی ها، حقوق و افزودن بازگشت اضافه می کند. هنگامی که بازتولید دقیق حقوق مورد نیاز نیست، یک کلید کافی است -r.
پس از کپی، متوجه می شویم که همه فایل ها کپی نشده اند - فایل هایی که با نقطه شروع می شوند:
.profile
.local
.mc
و مانند آن
چرا این اتفاق افتاد؟
زیرا حروف عام توسط پوسته پردازش می شوند (bash در یک مورد معمولی). بهطور پیشفرض، bash همه فایلهایی را که با نقطه شروع میشوند نادیده میگیرد، زیرا آنها را پنهان میکند. برای جلوگیری از این رفتار، باید رفتار خود را تغییر دهیم bash با استفاده از دستور:
shopt -s dotglob
برای اطمینان از تداوم این تغییر رفتار پس از راه اندازی مجدد، می توانید یک فایل wildcard.sh با این دستور در پوشه ایجاد کنید. /etc/profile.d (شاید توزیع شما پوشه متفاوتی داشته باشد).
و اگر هیچ فایلی در دایرکتوری منبع وجود نداشته باشد، پوسته نمی تواند چیزی را به جای ستاره جایگزین کند و کپی کردن نیز با خطا انجام نمی شود. گزینه هایی در برابر این وضعیت وجود دارد failglob и nullglob. ما نیاز به تنظیم خواهیم داشت failglob، که از اجرای دستور جلوگیری می کند. nullglob کار نخواهد کرد، زیرا رشته ای را با عبارات وحشی که مطابقتی پیدا نکرده است به یک رشته خالی (طول صفر) تبدیل می کند که برای cp باعث خطا خواهد شد.
با این حال، اگر هزاران فایل یا بیشتر در پوشه وجود داشته باشد، رویکرد عام باید به کلی کنار گذاشته شود. حقیقت این هست که bash حروف عام را به یک خط فرمان بسیار طولانی مانند:
cp -a /souce/a /source/b /source/c …… /target
محدودیتی در طول خط فرمان وجود دارد که با استفاده از دستور می توانیم آن را بفهمیم:
getconf ARG_MAX
بیایید حداکثر طول خط فرمان را بر حسب بایت بدست آوریم:
2097152
Или:
xargs --show-limits
ما چیزی شبیه به:
….
Maximum length of command we could actually use: 2089314
….
بنابراین، بیایید به طور کلی بدون عبارات کار کنیم.
فقط بنویسیم
cp -a /source /target
و در اینجا با ابهام رفتاری مواجه هستیم cp. اگر پوشه /target وجود نداشته باشد، آنچه را که نیاز داریم به دست خواهیم آورد.
با این حال، اگر پوشه هدف وجود داشته باشد، فایل ها در پوشه /target/source کپی می شوند.
ما همیشه نمیتوانیم پوشه /target را از قبل حذف کنیم، زیرا ممکن است حاوی فایلهای مورد نیاز ما باشد و هدف ما، برای مثال، تکمیل فایلهای موجود در /target با فایلهایی از منبع / است.
اگر نام پوشههای مبدا و مقصد یکسان بود، برای مثال، ما از /source به /home/source کپی میکردیم، میتوانیم از دستور استفاده کنیم:
cp -a /source /home
و پس از کپی، فایل های موجود در /home/source با فایل های /source تکمیل می شوند.
این یک مشکل منطقی است: اگر نام پوشهها یکسان باشد، میتوانیم فایلها را در فهرست مقصد اضافه کنیم، اما اگر متفاوت باشند، پوشه مبدا داخل مقصد قرار میگیرد. چگونه می توان فایل ها را از /source به /target با استفاده از cp بدون حروف عام کپی کرد؟
برای دور زدن این محدودیت مضر، از یک راه حل غیر واضح استفاده می کنیم:
cp -a /source/. /target
کسانی که با داس و لینوکس آشنا هستند قبلاً همه چیز را درک کرده اند: در داخل هر پوشه 2 پوشه نامرئی وجود دارد. و ".." که پیوندهای شبه پوشه ای به دایرکتوری های فعلی و بالاتر هستند.
هنگام کپی کردن cp وجود را بررسی می کند و سعی می کند /target/ را ایجاد کند.
چنین دایرکتوری وجود دارد و /target است
فایل های منبع / به درستی در /target کپی می شوند.
بنابراین، آن را در یک قاب پررنگ به یاد خود یا روی دیوار آویزان کنید:
cp -a /source/. /target
رفتار این دستور مشخص است. همه چیز بدون خطا کار خواهد کرد، صرف نظر از اینکه یک میلیون فایل دارید یا اصلاً هیچ.
یافته ها
اگر نیاز به کپی دارید همه فایل ها از یک پوشه به پوشه دیگر، ما از wildcard استفاده نمی کنیم، بهتر است به جای آن از آنها استفاده کنیم cp با یک نقطه در انتهای پوشه منبع ترکیب شده است. این کار همه فایلها، از جمله فایلهای مخفی را کپی میکند، و با میلیونها فایل یا بدون هیچ فایلی شکست نمیخورد.
پس از کلمه
vmspike یک نسخه فرمان با نتیجه مشابه را پیشنهاد کرد: