বাশের একটি মার্জিত লাইনের চেয়ে কয়েকটি জিনিস আমার কাছে বেশি সন্তোষজনক যা ঘন্টার ক্লান্তিকর কাজকে স্বয়ংক্রিয় করে।
Bash স্ক্রিপ্টের সাথে আমার ল্যাপটপকে স্বয়ংক্রিয়ভাবে পুনরায় তৈরি করার কিছু সাম্প্রতিক অনুসন্ধানের অংশ হিসাবে (আসতে হবে!), আমি একটি নতুন মেশিনে আমার GitHub-হোস্ট করা সংগ্রহস্থলগুলিকে সহজেই ক্লোন করার একটি উপায় খুঁজে পেতে চেয়েছিলাম। চারপাশে কিছুটা খনন করার পরে, আমি একটি ওয়ান-লাইনার লিখেছিলাম যা ঠিক তাই করেছিল।
তারপর, একই ঝুড়িতে আমাদের সমস্ত ডিম না রাখার চেতনায়, আমি স্বয়ংক্রিয়ভাবে গিটল্যাব-হোস্ট করা ব্যাকআপগুলি তৈরি করতে এবং পুশ করার জন্য আরেকটি ওয়ান-লাইনার লিখেছিলাম। এখানে তারা।
আপনার সমস্ত GitHub সংগ্রহস্থল ক্লোন করার জন্য একটি ব্যাশ ওয়ান-লাইনার
সতর্কতা:আপনি ক্লোন করতে চান এমন গিটহাব সংগ্রহস্থলগুলির একটি তালিকা আপনার প্রয়োজন হবে। এটির ভাল জিনিস হল এটি আপনাকে সম্পূর্ণ এজেন্সি দেয় যা আপনি আপনার মেশিনে চান এমন রিপোজিটরিগুলি বেছে নিতে পারেন, পুরো-হগের পরিবর্তে।
আপনি আপনার 15-মিনিটের ক্যাশেড শংসাপত্র সহ HTTPS ব্যবহার করে বা আমার পছন্দের পদ্ধতি, SSH-এর সাথে GitHub-এর সাথে সংযোগ করে প্রতিবার আপনার পাসওয়ার্ড না লিখে সহজেই GitHub সংগ্রহস্থলগুলি ক্লোন করতে পারেন। সংক্ষিপ্ততার জন্য আমি অনুমান করব যে আমরা পরবর্তীটির সাথে যাচ্ছি, এবং আমাদের SSH কীগুলি সেট আপ করা হয়েছে৷
gh-repos.txt
ফাইলে GitHub URL-এর একটি তালিকা দেওয়া হয়েছে , এই মত:
[email protected]:username/first-repository.git
[email protected]:username/second-repository.git
[email protected]:username/third-repository.git
আমরা চালাই:
xargs -n1 git clone < gh-repos.txt
এটি বর্তমান ফোল্ডারে তালিকার সমস্ত সংগ্রহস্থল ক্লোন করে। এই একই ওয়ান-লাইনার গিটল্যাবের জন্যও কাজ করে, যদি আপনি উপযুক্ত ইউআরএল প্রতিস্থাপন করেন।
এখানে কি হচ্ছে?
এই ওয়ান-লাইনারের দুটি অর্ধেক আছে:ইনপুট, কাউন্টারইন্টুটিভলি ডানদিকে, এবং যে অংশটি জিনিসগুলি ঘটতে দেয়, বাম দিকে। আমরা এই অংশগুলির ক্রমকে আরও স্বজ্ঞাত করতে পারি (হয়তো?) এইরকম একই কমান্ড লিখে:
<gh-repos.txt xargs -n1 git clone
আমাদের ইনপুটের প্রতিটি লাইনের জন্য একটি কমান্ড চালানোর জন্য, gh-repos.txt
, আমরা xargs -n1
ব্যবহার করি . টুল xargs
ইনপুট থেকে আইটেমগুলি পড়ে এবং এটি খুঁজে পাওয়া যেকোনো কমান্ড চালায় (এটি echo
হবে যদি এটি কোন খুঁজে না পায়)। ডিফল্টরূপে, এটি অনুমান করে যে আইটেমগুলি স্পেস দ্বারা পৃথক করা হয়েছে; নতুন লাইনগুলিও কাজ করে এবং আমাদের তালিকাকে পড়া সহজ করে তোলে। পতাকা -n1
xargs
বলে 1
ব্যবহার করতে যুক্তি, বা আমাদের ক্ষেত্রে, এক লাইন, প্রতি কমান্ড। আমরা git clone
দিয়ে আমাদের কমান্ড তৈরি করি , যা xargs
তারপর প্রতিটি লাইনের জন্য কার্যকর করে। তা-দা।
গিটল্যাবে অনেকগুলি সংগ্রহস্থল তৈরি এবং পুশ করার জন্য একটি ব্যাশ ওয়ান-লাইনার
গিটল্যাব, গিটহাবের বিপরীতে, আমাদের এই নিফটি জিনিসটি করতে দেয় যেখানে আমাদের প্রথমে একটি নতুন সংগ্রহস্থল তৈরি করতে ওয়েবসাইটটি ব্যবহার করতে হবে না। আমরা আমাদের টার্মিনাল থেকে একটি নতুন GitLab সংগ্রহস্থল তৈরি করতে পারি। নতুন তৈরি করা রিপোজিটরি ডিফল্ট হিসেবে প্রাইভেট হিসেবে সেট করা হয়েছে, তাই আমরা যদি এটিকে GitLab-এ সর্বজনীন করতে চাই, তাহলে আমাদের পরে ম্যানুয়ালি করতে হবে।
গিটল্যাব ডক্স আমাদেরকে git push --set-upstream
ব্যবহার করে একটি নতুন প্রকল্প তৈরি করার জন্য চাপ দিতে বলে। , কিন্তু আমি এটিকে ব্যাকআপ হিসাবে গিটল্যাব ব্যবহার করার জন্য খুব সুবিধাজনক বলে মনে করি না। আমি ভবিষ্যতে আমার সংগ্রহস্থলগুলির সাথে কাজ করার সময়, আমি একটি কমান্ড চালাতে চাই যা GitHub এবং উভয়ের দিকে ঠেলে দেয় আমার পক্ষ থেকে অতিরিক্ত প্রচেষ্টা ছাড়াই গিটল্যাব।
এই ব্যাশ ওয়ান-লাইনার কাজ করার জন্য, আমাদের গিটল্যাবের জন্য রিপোজিটরি ইউআরএলগুলির একটি তালিকাও প্রয়োজন হবে (যেগুলি এখনও বিদ্যমান নেই)। আমরা আমাদের GitHub সংগ্রহস্থলের তালিকা অনুলিপি করে, Vim-এর সাথে এটি খুলতে এবং অনুসন্ধান-এবং-প্রতিস্থাপন করে এটি সহজেই করতে পারি:
cp gh-repos.txt gl-repos.txt
vim gl-repos.txt
:%s/\<github\>/gitlab/g
:wq
এটি gl-repos.txt
তৈরি করে , যা এর মত দেখাচ্ছে:
[email protected]:username/first-repository.git
[email protected]:username/second-repository.git
[email protected]:username/third-repository.git
আমরা গিটল্যাবে এই সংগ্রহস্থলগুলি তৈরি করতে পারি, ইউআরএলগুলিকে রিমোট হিসাবে যুক্ত করতে পারি এবং আমাদের কোডগুলিকে চালানোর মাধ্যমে নতুন সংগ্রহস্থলগুলিতে পুশ করতে পারি:
awk -F'\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt
অপেক্ষা করুন এবং আমি এটি ব্যাখ্যা করব; আপাতত, মনে রাখবেন যে ~/FULL/PATH/
আমাদের GitHub সংগ্রহস্থল ধারণকারী ডিরেক্টরির সম্পূর্ণ পথ হওয়া উচিত।
আমাদের কয়েকটি অনুমান নোট করতে হবে:
- আপনার স্থানীয় মেশিনে যে ডাইরেক্টরিটির নাম রিপোজিটরি রয়েছে সেটি ইউআরএল-এ থাকা রিপোজিটরির নামের মতোই (উপরের ওয়ান-লাইনার দিয়ে ক্লোন করা হলে সেটাই হবে);
- প্রতিটি সংগ্রহস্থল বর্তমানে আপনি যে শাখায় ঠেলে দিতে চান সেখানে চেক আউট করা হয়, যেমন।
master
.
এই অনুমানগুলি পরিচালনা করার জন্য ওয়ান-লাইনারটি প্রসারিত করা যেতে পারে, তবে এটি লেখকের বিনীত মতামত যে সেই সময়ে, আমাদের সত্যিই একটি ব্যাশ স্ক্রিপ্ট লেখা উচিত।
এখানে কি হচ্ছে?
আমাদের ব্যাশ ওয়ান-লাইনার gl-repos.txt
-এ প্রতিটি লাইন (বা URL) ব্যবহার করে ইনপুট হিসাবে ফাইল। awk
দিয়ে , এটি আমাদের স্থানীয় মেশিনে সংগ্রহস্থল ধারণকারী ডিরেক্টরির নামকে বিভক্ত করে, এবং আমাদের বৃহত্তর কমান্ড তৈরি করতে এই তথ্যের টুকরোগুলি ব্যবহার করে। আমরা যদি print
করতাম awk
এর আউটপুট , আমরা দেখতে চাই:
cd ~/FULL/PATH/first-repository && git remote set-url origin --add [email protected]:username/first-repository.git && git push
cd ~/FULL/PATH/second-repository && git remote set-url origin --add [email protected]:username/second-repository.git && git push
cd ~/FULL/PATH/third-repository && git remote set-url origin --add [email protected]:username/third-repository.git && git push
আসুন দেখি কিভাবে আমরা এই কমান্ডটি তৈরি করি।
awk
দিয়ে স্ট্রিং বিভক্ত করা
টুল awk
ক্ষেত্র বিভাজক উপর ভিত্তি করে ইনপুট বিভক্ত করতে পারেন. ডিফল্ট বিভাজক একটি হোয়াইটস্পেস অক্ষর, কিন্তু আমরা -F
পাস করে এটি পরিবর্তন করতে পারি পতাকা একক অক্ষর ছাড়াও, আমরা একটি রেগুলার এক্সপ্রেশন ফিল্ড সেপারেটরও ব্যবহার করতে পারি। যেহেতু আমাদের সংগ্রহস্থলের URL-এর একটি সেট বিন্যাস রয়েছে, তাই আমরা \/
স্ল্যাশ অক্ষরের মধ্যে সাবস্ট্রিং জিজ্ঞাসা করে সংগ্রহস্থলের নামগুলি ধরতে পারি। এবং URL এর শেষে, .git
.
এটি সম্পন্ন করার একটি উপায় হল আমাদের regex \/|(\.git)
:
\/
একটি পালানো\/
চরিত্র;|
মানে "অথবা", awk কে বলা যেকোন একটি এক্সপ্রেশনের সাথে মেলে;(\.git)
আমাদের URL-এর শেষে ক্যাপচার গ্রুপ যা “.git” এর সাথে মেলে, একটি পালানো.
চরিত্র এটি কিছুটা প্রতারণার বিষয়, কারণ ".git" কঠোরভাবে কোনো কিছুকে বিভক্ত করে না (অন্যদিকে কিছুই নেই) তবে এটি আমাদের জন্য এটিকে সরিয়ে নেওয়ার একটি সহজ উপায়৷
একবার আমরা awk
বলেছি যেখানে বিভক্ত করতে হবে, আমরা ফিল্ড অপারেটরের সাথে সঠিক সাবস্ট্রিং ধরতে পারি। আমরা একটি $
দিয়ে আমাদের ক্ষেত্র উল্লেখ করি অক্ষর, তারপর ক্ষেত্রের কলাম সংখ্যা দ্বারা। আমাদের উদাহরণে, আমরা দ্বিতীয় ক্ষেত্র চাই, $2
. এখানে সমস্ত সাবস্ট্রিংগুলি কেমন দেখায়:
1: [email protected]:username
2: first-repository
পুরো স্ট্রিং ব্যবহার করতে, বা আমাদের ক্ষেত্রে, পুরো URL, আমরা ফিল্ড অপারেটর ব্যবহার করি $0
. কমান্ড লেখার জন্য, আমরা শুধু রিপোজিটরি নাম এবং URL এর জন্য ফিল্ড অপারেটরগুলিকে প্রতিস্থাপন করি। এটি print
দিয়ে চালানো হচ্ছে যেহেতু আমরা নির্মাণ করছি এটি নিশ্চিত করতে সাহায্য করতে পারে যে আমরা সমস্ত স্থান ঠিকভাবে পেয়েছি৷
awk -F'\/|(\.git)' '{print "cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push"}' gl-repos.txt
কমান্ড চালানো হচ্ছে
আমরা system()
এর বন্ধনীর ভিতরে আমাদের কমান্ড তৈরি করি . এটিকে awk
এর আউটপুট হিসাবে ব্যবহার করে , প্রতিটি কমান্ড বিল্ট এবং আউটপুট হওয়ার সাথে সাথেই চলবে। system()
ফাংশন একটি চাইল্ড প্রসেস তৈরি করে যা আমাদের কমান্ড এক্সিকিউট করে, তারপর কমান্ড সম্পূর্ণ হলে রিটার্ন করে। সরল ইংরেজিতে, এটি আমাদের প্রতিটি রিপোজিটরিতে গিট কমান্ডগুলি সম্পাদন করতে দেয়, আমাদের মূল প্রক্রিয়া যা awk
আমাদের ইনপুট ফাইলের সাথে কাজ করছে। এখানে আবার আমাদের চূড়ান্ত আদেশ, সবগুলো একসাথে।
awk -F'\/|(\.git)' '{system("cd ~/FULL/PATH/" $2 " && git remote set-url origin --add " $0 " && git push")}' gl-repos.txt
আমাদের ব্যাকআপগুলি ব্যবহার করা
৷
রিমোট হিসাবে গিটল্যাব ইউআরএল যোগ করে, আমরা বাহ্যিকভাবে হোস্ট করা উভয় রিপোজিটরিতে পুশ করার প্রক্রিয়াটিকে সহজ করেছি। যদি আমরা git remote -v
চালাই আমাদের সংগ্রহস্থল ডিরেক্টরিগুলির একটিতে, আমরা দেখতে পাব:
origin [email protected]:username/first-repository.git (fetch)
origin [email protected]:username/first-repository.git (push)
origin [email protected]:username/first-repository.git (push)
এখন, শুধু git push
চালান যুক্তি ছাড়াই বর্তমান শাখাটিকে উভয় দূরবর্তী সংগ্রহস্থলে ঠেলে দেবে।
আমাদের আরও লক্ষ্য করা উচিত যে git pull
সাধারণত আপনি যে রিমোট রিপোজিটরি থেকে মূলত ক্লোন করেছিলেন তা থেকে টেনে আনার চেষ্টা করবে (URL চিহ্নিত (fetch)
উপরের আমাদের উদাহরণে)। একই সময়ে একাধিক গিট রিপোজিটরি থেকে টানা সম্ভব, তবে জটিল এবং এই পোস্টের সুযোগের বাইরে। আপনি যদি কৌতূহলী হন তবে আপনাকে শুরু করতে সহায়তা করার জন্য এখানে একাধিক রিমোটে ধাক্কা দেওয়া এবং টানার একটি ব্যাখ্যা রয়েছে। রিমোটে গিট ডকুমেন্টেশনও সহায়ক হতে পারে।
ব্যাশ ওয়ান-লাইনারের সংক্ষিপ্ততা সম্পর্কে বিস্তারিত জানার জন্য
ব্যাশ ওয়ান-লাইনার, যখন বোঝা যায়, মজাদার এবং সহজ শর্টকাট হতে পারে। অন্ততপক্ষে, xargs
এর মত টুল সম্পর্কে সচেতন হওয়া এবং awk
স্বয়ংক্রিয়ভাবে সাহায্য করতে পারে এবং আমাদের কাজের অনেক ক্লান্তি দূর করতে পারে। যাইহোক, কিছু খারাপ দিক আছে।
সহজে বোঝা যায়, রক্ষণাবেক্ষণ করা যায়, এবং অ্যাক্সেসযোগ্য টুলের পরিপ্রেক্ষিতে, ব্যাশ ওয়ান-লাইনার চুষে যায়। এগুলি সাধারণত if
ব্যবহার করে ব্যাশ স্ক্রিপ্টের চেয়ে লিখতে আরও জটিল অথবা while
loops, এবং অবশ্যই পড়তে আরও জটিল। এটা সম্ভবত যে আমরা যখন সেগুলি লিখি, আমরা কোথাও একটি একক উদ্ধৃতি বা বন্ধ বন্ধনী মিস করব; এবং আমি আশা করি এই পোস্টটি দেখায়, তারাও বেশ কিছুটা ব্যাখ্যা করতে পারে। তাহলে কেন এগুলো ব্যবহার করবেন?
একটি কেক বেক করার জন্য একটি রেসিপি পড়ার কল্পনা করুন, ধাপে ধাপে। আপনি পদ্ধতি এবং উপাদানগুলি বোঝেন এবং আপনার সরবরাহ সংগ্রহ করুন। তারপরে, আপনি এটি সম্পর্কে চিন্তা করার সাথে সাথে আপনি বুঝতে শুরু করেন যে আপনি যদি সমস্ত উপাদানগুলিকে সঠিকভাবে ওভেনে নিক্ষেপ করেন তবে একটি কেক তাত্ক্ষণিকভাবে বাস্তবায়িত হবে। আপনি এটি চেষ্টা করুন, এবং এটি কাজ করে!
এটা বেশ সন্তোষজনক হবে, তাই না?