আমার কাছে অনেকগুলি ফাইল রয়েছে যা একটি ডিরেক্টরিতে ফাইলের নাম অনুসারে অর্ডার করা হয়। আমি আমার হোম ডিরেক্টরিতে চূড়ান্ত এন (বলে, এন = 4) ফাইলগুলি অনুলিপি করতে চাই। আমি এটা কিভাবে করব?
cp ./<the final 4 files> ~/
আমার কাছে অনেকগুলি ফাইল রয়েছে যা একটি ডিরেক্টরিতে ফাইলের নাম অনুসারে অর্ডার করা হয়। আমি আমার হোম ডিরেক্টরিতে চূড়ান্ত এন (বলে, এন = 4) ফাইলগুলি অনুলিপি করতে চাই। আমি এটা কিভাবে করব?
cp ./<the final 4 files> ~/
উত্তর:
এটি সহজেই ব্যাশ / ksh93 / zsh অ্যারে দিয়ে করা যেতে পারে:
a=(*)
cp -- "${a[@]: -4}" ~/
এটি সমস্ত অ-গোপন ফাইল ফাইলের জন্য কাজ করে এমনকি সেগুলিতে স্পেস, ট্যাব, নিউলাইনস বা অন্যান্য কঠিন অক্ষর রয়েছে (ধরে নিলে বর্তমান ডিরেক্টরিটিতে কমপক্ষে 4 টি গোপনীয় ফাইল রয়েছে বলে ধরে নেওয়া যায় bash
)।
a=(*)
এটি a
সমস্ত ফাইলের নামের সাথে একটি অ্যারে তৈরি করে । বাশ দ্বারা ফিরিয়ে দেওয়া ফাইলের নাম বর্ণমালা অনুসারে বাছাই করা হয়। (আমি ধরে নিলাম যে এটিই "ফাইলের নাম অনুসারে অর্ডার করা হয়েছে" বলতে চাইছেন )
${a[@]: -4}
এটি অ্যারের শেষ চারটি উপাদান ফেরত দেয় a
(প্রদত্ত অ্যারেতে কমপক্ষে 4 টি উপাদান থাকে bash
)।
cp -- "${a[@]: -4}" ~/
এটি আপনার হোম ডিরেক্টরিতে সর্বশেষ চারটি ফাইলের নাম অনুলিপি করে।
এটি কেবলমাত্র হোম ডিরেক্টরিতে সর্বশেষ চারটি ফাইল অনুলিপি করবে এবং একই সময়ে a_
অনুলিপি করা ফাইলটির নামে স্ট্রিংটি প্রিন্ট করবে :
a=(*)
for fname in "${a[@]: -4}"; do cp -- "$fname" ~/a_"$fname"; done
যদি আমরা এর a=(./some_dir/*)
পরিবর্তে ব্যবহার করি a=(*)
, তবে আমাদের ডিরেক্টরিটি ফাইলের সাথে সংযুক্ত হওয়ার বিষয়টি আছে। একটি সমাধান হ'ল:
a=(./some_dir/*)
for f in "${a[@]: -4}"; do cp "$f" ~/a_"${f##*/}"; done
আরেকটি সমাধান হ'ল সাব-শেল ব্যবহার এবং সাব-শেলের cd
ডিরেক্টরিতে:
(cd ./some_dir && a=(*) && for f in "${a[@]: -4}"; do cp -- "$f" ~/a_"$f"; done)
সাবশেলটি সমাপ্ত হলে শেল আমাদের মূল ডিরেক্টরিতে ফিরিয়ে দেয়।
প্রশ্নটি "ফাইলের নাম অনুসারে অর্ডার করা" ফাইলগুলির জন্য জিজ্ঞাসা করে। এই আদেশ, অলিভিয়ার ডুলাক মন্তব্যগুলিতে উল্লেখ করেছেন, এক লোকাল থেকে অন্য অঞ্চলে পৃথক হবে। যদি মেশিন সেটিংস থেকে পৃথক ফলাফল নির্ধারণ করা গুরুত্বপূর্ণ, তবে অ্যারে a
সংজ্ঞায়িত করা হলে স্পষ্টতই লোকাল নির্দিষ্ট করা ভাল । উদাহরণ স্বরূপ:
LC_ALL=C a=(*)
locale
কমান্ডটি চালিয়ে আপনি বর্তমানে কোন লোকালয়ে রয়েছেন তা সন্ধান করতে পারেন ।
আপনি যদি ব্যবহার করছেন তবে zsh
আপনি বন্ধুত্বের মধ্যে বন্ধক রাখতে()
পারেন তথাকথিত গ্লোব কোয়ালিফায়ারগুলির একটি তালিকা যা পছন্দসই ফাইল নির্বাচন করে। আপনার ক্ষেত্রে, এটি হবে
cp *(On[1,4]) ~/
এখানে On
বিপরীত ক্রমে নাম বর্ণ অনুসারে বাছাই করা হয় এবং এর মধ্যে [1,4]
কেবল প্রথম 4 টি লাগে।
আপনি কেবল প্লেইন ফাইল (ডিরেক্টরি, পাইপ ইত্যাদি বাদ দিয়ে) নির্বাচন করে .
এবং নামগুলি সঠিকভাবে শুরু হওয়া ফাইলগুলির চিকিত্সার --
জন্য cp
কমান্ড যোগ করে আরও শক্তিশালী করতে পারেন -
, সুতরাং:
cp -- *(.On[1,4]) ~
D
আপনি যদি লুকানো ফাইলগুলি (ডট-ফাইল) বিবেচনা করতে চান তবে যোগ্যতা যুক্ত করুন :
cp -- *(D.On[1,4]) ~
*([-4,-1])
।
on
) ডিফল্ট আচরণ, সুতরাং এটি নির্দিষ্ট করার দরকার নেই এবং -
সংখ্যার সামনে নীচে থেকে ফাইলের নাম গণনা করা হয়।
অত্যন্ত সরল বাশ কমান্ড ব্যবহার করে একটি সমাধান এখানে দেওয়া হল।
find . -maxdepth 1 -type f | sort | tail -n 4 | while read -r file; do cp "$file" ~/; done
ব্যাখ্যা:
find . -maxdepth 1 -type f
বর্তমান ডিরেক্টরিতে সমস্ত ফাইল সন্ধান করে।
sort
বর্ণমালা অনুসারে বাছাই করুন।
tail -n 4
কেবলমাত্র শেষ 4 টি লাইন দেখান।
while read -r file; do cp "$file" ~/; done
অনুলিপি কমান্ড সম্পাদন করে প্রতিটি লাইনের উপরে লুপ করে।
যতক্ষণ আপনি শেল সাজানোর পক্ষে সম্মতিজনক তা খুঁজে পান, আপনি কেবল এটি করতে পারেন:
set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
cp "$@" /path/to/target/dir
এটি bash
প্রদত্ত-স্পেসিফিক অ্যারে সমাধানের সাথে খুব মিল , তবে কোনও পসিক্স-সামঞ্জস্যপূর্ণ শেলের কাছে পোর্টেবল হওয়া উচিত। উভয় পদ্ধতি সম্পর্কে কিছু নোট:
আপনি আপনার cp
যুক্তি ডব্লিউ / cp --
বা আপনি যে কোনও .
বিন্দুর মধ্যে একটি বা /
প্রতিটি নামের শিরোনামে পেতে পারেন তা গুরুত্বপূর্ণ lead আপনি যদি এটি করতে ব্যর্থ হন তবে আপনি প্রথম যুক্তিতে নেতৃস্থানীয় -
ড্যাশ ঝুঁকিপূর্ণ cp
যা বিকল্প হিসাবে ব্যাখ্যা করা যেতে পারে এবং অপারেশনটিকে ব্যর্থ হতে পারে বা অন্যথায় অনিচ্ছাকৃত ফলাফল সরবরাহ করতে পারে।
set -- ./*
বা হিসাবে সম্পন্ন হয় array=(./*)
।আপনার আরগ অ্যারে কমপক্ষে যতগুলি আইটেম আপনি মুছে ফেলার চেষ্টা করছেন তা নিশ্চিত করার জন্য উভয় পদ্ধতি ব্যবহার করার সময় এটি গুরুত্বপূর্ণ - আমি এখানে একটি গণিতের বিস্তার দিয়ে তা করি। shift
শুধুমাত্র তখনই ঘটে যদি ARG অ্যারের মধ্যে অন্তত 4 আইটেম নেই - এবং তারপর শুধুমাত্র বদল আনতে দূরে যারা প্রথম args 4 একটি উদ্বৃত্ত করা ..
set 1 2 3 4 5
ক্ষেত্রে এটি 1
দূরে স্থানান্তরিত হবে , তবে একটি set 1 2 3
ক্ষেত্রে এটি কিছুই বদলবে না।a=(1 2 3); echo "${a[@]: -4}"
একটি ফাঁকা রেখা প্রিন্ট করে।আপনি যদি একটি ডিরেক্টরি থেকে অন্য ডিরেক্টরিতে অনুলিপি করছেন তবে আপনি ব্যবহার করতে পারেন pax
:
set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
pax -rws '|.*/|new_prefix|' "$@" /path/to/target/dir
... যা sed
এগুলি অনুলিপি করার সাথে সাথে সমস্ত ফাইল নামগুলিতে স্টাইলের বিকল্প প্রয়োগ করবে।
যদি কেবলমাত্র ফাইল থাকে এবং তাদের নামগুলিতে শ্বেতক্ষেত্র বা নিউলাইন (এবং আপনি কোনও সংশোধন করেননি $IFS
) বা গ্লোব অক্ষর (বা কিছু প্রিন্টযোগ্য অক্ষর যার কিছু প্রয়োগ রয়েছে ls
) দিয়ে না শুরু করেন .
, তবে আপনি এটি করতে পারেন :
cp -- $(ls | tail -n 4) ~/
a_
সমস্ত চারটি ফাইলের উপসর্গটি কীভাবে দ্রুত প্রপেন্ড করা যায়? আমি চেষ্টা করেছি echo "a_$(ls | tail -n 4)"
, তবে এটি কেবলমাত্র প্রথম ফাইলটিকেই সংশোধন করে।
ls
আউটপুটটিকে খারাপ ফর্ম হিসাবে বিবেচনা করা হয় কারণ এটি সাধারণত ফাইলের নামগুলিতে মারাত্মকভাবে ব্যর্থ হয় যা কেবলমাত্র ফাঁকা স্থান নয়, তবে ট্যাব, নিউলাইনগুলি বা অন্যান্য বৈধ তবে "কঠিন" অক্ষরও রাখে।
এটি কোনও লুপ কোড ছাড়াই একটি সহজ বাশ সমাধান। বর্তমান দির থেকে শেষ 4 টি ফাইল গন্তব্যে অনুলিপি করুন:
$ find . -maxdepth 1 -type f |tail -n -4|xargs cp -t "$destdir"
find
এটি আপনাকে পছন্দসই ক্রমে ফাইলগুলি দেয়? আপনি কীভাবে নিশ্চিত করতে পারেন যে তাদের নামগুলিতে হোয়াইটস্পেস অক্ষরযুক্ত ফাইলগুলি (নিউলাইনগুলি সহ) সঠিকভাবে পরিচালনা করা হয়েছে?
LC_ALL=C