دستور cp: کپی صحیح پوشه های فایل در *nix

دستور cp: کپی صحیح پوشه های فایل در *nix

این مقاله برخی از موارد غیر واضح مربوط به استفاده از آن را نشان می دهد کارت های وحشی هنگام کپی کردن، رفتار دستور مبهم 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 یک نسخه فرمان با نتیجه مشابه را پیشنهاد کرد:

cp -a -T /source /target

اوز_الکس

cp -aT /source /target

توجه: مورد نامه T معنی دارد. اگر آن را با هم مخلوط کنید، یک آشغال کامل دریافت خواهید کرد: جهت کپی تغییر خواهد کرد.
تشکر و قدردانی:

  • شرکتها RUVDS.COM برای حمایت و فرصتی برای انتشار در وبلاگ خود در Habré.
  • در هر تصویر مفهوم سه گانه. تصویر بسیار بزرگ و با جزئیات است، می تواند در یک پنجره جداگانه باز شود.

PS لطفا هر خطایی که متوجه شدید در پیام خصوصی ارسال کنید. من برای این کارم را افزایش می دهم.

دستور cp: کپی صحیح پوشه های فایل در *nix

منبع: www.habr.com

اضافه کردن نظر