کنوانسیون نامگذاری پرونده های Bash بسیار غنی هستند و ایجاد یک اسکریپت یا یک خط آسان که باعث تجزیه اشتباه نام فایل ها شود آسان است. بیاموزید که نام پرونده ها را به درستی تجزیه و تحلیل کنید و بنابراین مطمئن شوید که اسکریپت های شما مطابق هدف کار می کنند!
مشکل در تجزیه و تحلیل صحیح نام پرونده ها در Bash
اگر مدتی است که از Bash استفاده کرده اید و اسکریپت هایی را به زبان باشکوه Bash آن نوشته اید ، به احتمال زیاد با برخی از مشکلات تجزیه نام فایل روبرو خواهید شد. بیایید به یک مثال ساده از آنچه ممکن است اشتباه رخ دهد نگاه کنیم:
touch 'a > b'
در اینجا ما یک پرونده ایجاد کردیم که در واقع وجود دارد CR
(کالسکه را برگردانید) ، با فشار دادن enter پس از آن وارد آن شوید a
. کنوانسیون نامگذاری فایل های Bash بسیار غنی هستند ، و گرچه به نوعی جالب است ، اما می توانیم از نویسه های خاصی مانند آنهایی که در یک نام فایل هستند استفاده کنیم ، اما بیایید ببینیم که چگونه این پرونده محاسبه می شود:
ls | xargs rm
این کار نمی کند. xargs
ورودی را از ls
(از طريق |
لوله) و آن را منتقل کنید rm
اما مشکلی پیش آمد!
آنچه اشتباه رخ داده این است که راه برون رفت از آن است ls
به معنای واقعی کلمه توسط xargs
و “ورود” (CR
– Carriage Return) در نام پرونده از قابل مشاهده است xargs
به عنوان یک خاتمه واقعی ، نه به عنوان CR
تسلیم شدن در برابر rm
همانطور که باید باشد.
بگذارید به روش دیگری بیان کنیم:
ls | xargs -I{} echo '{}|'
واضح است: xargs
ورودی را به عنوان دو خط جداگانه در نظر می گیرد ، نام پرونده اصلی را به دو قسمت تقسیم می کند! حتی اگر مجبور شدیم از طریق تجزیه فوق العاده با استفاده از sed ، مشکلات فضایی را اصلاح کنیم ، به زودی هنگام شروع استفاده از کاراکترهای خاص دیگر مانند فضاها ، بک شلش ها ، نقل قول ها و موارد دیگر ، با مشکلات دیگری روبرو خواهیم شد!
touch 'a b' touch 'a b' touch 'ab' touch 'a"b' touch "a'b" ls
حتی اگر شما یک توسعه دهنده باتجربه Bash باشید ، ممکن است از دیدن نام پرونده های این چنینی به لرزه درآید ، زیرا تجزیه و تحلیل صحیح این پرونده ها برای ابزارهای Bash که معمولاً استفاده می شود بسیار دشوار است. برای اینکه این کار انجام شود ، باید در رشته ها تغییراتی ایجاد کنید. یعنی مگر اینکه دستور پنهانی داشته باشید.
قبل از اینکه به این موضوع بپردازیم ، یک چیز دیگر وجود دارد – شما باید بدانید – که ممکن است در تجزیه و تحلیل قرار بگیرید ls
خارج شدن اگر از کدگذاری رنگی برای لیست های فهرست استفاده می کنید ، که به طور پیش فرض در اوبونتو فعال است ، پیوستن به مجموعه دیگری از ls
تحلیل مسئله
آنها در واقع به نحوه نامگذاری پرونده ها مربوط نیستند بلکه بیشتر به نحوه ارائه پرونده ها به عنوان خروجی مربوط می شوند ls
. ls
خروجی حاوی کدهای هگزادسیمال است که نشان دهنده رنگی است که برای ترمینال شما استفاده می شود.
برای جلوگیری از مواجهه با آنها ، فقط استفاده کنید --color=never
به عنوان گزینه ای برای ls
:ls --color=never
.
در Mint 20 (سیستم عامل مشتق بزرگی از اوبونتو) این مشکل برطرف شده است ، اگرچه ممکن است این مشکل هنوز در بسیاری از نسخه های دیگر یا قدیمی اوبونتو و غیره وجود داشته باشد. من این مشکل را از اواسط آگوست سال 2020 در اوبونتو دیدم.
حتی اگر از کدگذاری رنگ برای لیست های فهرست خود استفاده نکنید ، ممکن است اسکریپت شما روی سیستم های دیگری که تحت مالکیت و مدیریت شما نیستند نیز اجرا شود. در این حالت ، شما همچنین می خواهید از این گزینه برای جلوگیری از کار کاربران چنین دستگاهی با مشکل توصیف شده استفاده کنید.
با بازگشت به دستور مخفی ما ، بیایید نگاهی بیندازیم که چگونه می توانیم اطمینان حاصل کنیم که با شخصیت های خاص در نام پرونده Bash مشکلی نداریم. محلول ارائه شده از هرگونه استفاده جلوگیری می کند ls
، که خوب است به طور کلی از آن اجتناب شود ، بنابراین مشکلات کدگذاری رنگ نیز قابل اجرا نیست.
هنوز مواقعی وجود دارد که ls
تجزیه سریع و راحت است ، اما به محض معرفی شخصیت های خاص همیشه پیچیده و احتمالاً “کثیف” خواهد بود – ناگفته نماند ناامن است (برای ورود به هر مشکلی می توان از شخصیت های خاص استفاده کرد).
دستورالعمل راز: NULL را خاتمه دهید
توسعه دهندگان ابزار Bash سالها قبل به همین مشکل پی بردند و موارد زیر را برای ما فراهم کردند: NULL
خاتمه دادن!
چیست NULL
ختم بپرسید؟ مانند مثالهای بالا در نظر بگیرید ، CR
(یا به معنای واقعی کلمه وارد) علامت اصلی فسخ بود.
ما همچنین دیده ایم که چگونه می توان از کاراکترهای خاص مانند نقل قول ها ، فاصله ها و برش ها در نام پرونده ها استفاده کرد ، اگرچه هنگام استفاده از ابزارهای دیگر برای تجزیه و تحلیل و اصلاح متن Bash مانند sed ، ویژگی های خاصی دارند. حالا این را با مقایسه کنید -0
گزینه برای گارگ، از جانب man xargs
:
-0 ، -صفر عناصر ورودی به جای یک فضای خالی با یک کاراکتر صفر خاتمه می یابند و علامت نقل قول و بک اسلش خاص نیستند (هر کاراکتر به معنای واقعی کلمه گرفته می شود). پایان رشته فایل را غیرفعال می کند ، که مانند هر بحث دیگری درمان می شود. زمانی مفید است که عناصر وارد شده ممکن است حاوی فضای خالی ، علامت نقل قول یا عقب باشد. گزینه GNU find -print0 ورودی مناسبی برای این حالت ایجاد می کند.
و -print0
گزینه برای find
، از جانب man find
:
-fprint0 فایل درست است، واقعی؛ نام پرونده کامل خروجی استاندارد را چاپ کنید و به دنبال آن یک کاراکتر صفر قرار دهید (به جای کاراکتر خط جدیدی که -print از آن استفاده می کند). این اجازه می دهد تا نام پرونده هایی که حاوی خطوط جدید یا انواع دیگری از فضای خالی هستند توسط برنامه هایی که خروجی find را پردازش می کنند به درستی تفسیر شوند. این گزینه با گزینه -0 xargs مطابقت دارد.
درست است، واقعی؛ در اینجا به معنای اگر گزینه مشخص شده باشد ، موارد زیر درست است.. جالب توجه هر دو اخطار واضح است که در جای دیگر صفحه همان کتابچه راهنما داده شده است:
- اگر خروجی find را در برنامه دیگری وارد کنید و کوچکترین احتمال وجود دارد که پرونده های مورد نظر شما دارای یک خط جدید باشند ، باید به طور جدی استفاده از گزینه -print0 را به جای -print بررسی کنید. برای اطلاعات در مورد نحوه کاراکترهای غیرمعمول در نام پرونده ها به بخش FILENIMS غیرمعمول مراجعه کنید.
- اگر از find در یک اسکریپت یا موقعیتی استفاده می کنید که پرونده های منطبق می توانند نام تصادفی داشته باشند ، باید به جای -print از -print0 استفاده کنید.
این هشدارهای واضح به ما یادآوری می کند که تجزیه و تحلیل نام پرونده ها در bash می تواند تجارت سختی باشد و باشد. با این حال ، با گزینه های مناسب بله find
، برای مثال -print0
، و xargs
، برای مثال -0
، تمام کاراکترهای خاص ما که دارای نام فایل هستند می توانند به درستی تجزیه و تحلیل شوند:
ls find . -name 'a*' -print0 find . -name 'a*' -print0 | xargs -0 ls find . -name 'a*' -print0 | xargs -0 rm
ابتدا لیستی از فهرست ها را بررسی می کنیم. همه نام پرونده های ما حاوی نویسه های خاص در آنجا است. سپس ما آن را به سادگی انجام می دهیم find ... -print0
برای دیدن خروجی توجه داشته باشید که رشته ها هستند NULL
خاتمه یافته (ها) NULL
یا