একটি ডিরেক্টরিতে শেষ এন ফাইলগুলি কীভাবে পাবেন?


15

আমার কাছে অনেকগুলি ফাইল রয়েছে যা একটি ডিরেক্টরিতে ফাইলের নাম অনুসারে অর্ডার করা হয়। আমি আমার হোম ডিরেক্টরিতে চূড়ান্ত এন (বলে, এন = 4) ফাইলগুলি অনুলিপি করতে চাই। আমি এটা কিভাবে করব?

cp ./<the final 4 files> ~/


1
নীচের সমস্ত উত্তরের উপর, আপনাকে রেঞ্জগুলি ব্যবহার করে কমান্ডগুলির সামনে একটি "LC_ALL = ..." যুক্ত করার প্রয়োজন হতে পারে, যাতে তাদের রেঞ্জগুলি আপনার জন্য সঠিক লোকেল ব্যবহার করে (লোকেলগুলি পরিবর্তন করতে পারে এবং অক্ষরের ক্রম পরিবর্তন করতে পারে) অনেক কিছু, উদাহরণস্বরূপ, কিছু লোকেলগুলিতে [আজ] বর্ণগুলিতে "জেড" ব্যতীত বর্ণমালার সমস্ত অক্ষর থাকতে পারে, যেমন: অক্ষরগুলি আদেশ করা হয়েছে: এএবিবিসিসি .... জেডজেড। অন্যান্য প্রকারের উপস্থিতি রয়েছে (উচ্চারণযোগ্য বর্ণ এবং আরও বহিরাগত অর্ডার) )। সাধারণ পছন্দটি হ'ল:LC_ALL=C
অলিভিয়ার ডুলাক

উত্তর:


23

এটি সহজেই ব্যাশ / 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কমান্ডটি চালিয়ে আপনি বর্তমানে কোন লোকালয়ে রয়েছেন তা সন্ধান করতে পারেন ।


9

আপনি যদি ব্যবহার করছেন তবে zshআপনি বন্ধুত্বের মধ্যে বন্ধক রাখতে() পারেন তথাকথিত গ্লোব কোয়ালিফায়ারগুলির একটি তালিকা যা পছন্দসই ফাইল নির্বাচন করে। আপনার ক্ষেত্রে, এটি হবে

cp *(On[1,4]) ~/

এখানে Onবিপরীত ক্রমে নাম বর্ণ অনুসারে বাছাই করা হয় এবং এর মধ্যে [1,4]কেবল প্রথম 4 টি লাগে।

আপনি কেবল প্লেইন ফাইল (ডিরেক্টরি, পাইপ ইত্যাদি বাদ দিয়ে) নির্বাচন করে .এবং নামগুলি সঠিকভাবে শুরু হওয়া ফাইলগুলির চিকিত্সার --জন্য cpকমান্ড যোগ করে আরও শক্তিশালী করতে পারেন -, সুতরাং:

cp -- *(.On[1,4]) ~

Dআপনি যদি লুকানো ফাইলগুলি (ডট-ফাইল) বিবেচনা করতে চান তবে যোগ্যতা যুক্ত করুন :

cp -- *(D.On[1,4]) ~


2
@ স্টাফেনচাজেলাস হ্যাঁ, ভবিষ্যতের পাঠকদের জন্য স্পষ্ট করে বলতে দিন যে স্বাভাবিক দিকের বর্ণমালা অনুসারে বাছাই করা ( on) ডিফল্ট আচরণ, সুতরাং এটি নির্দিষ্ট করার দরকার নেই এবং -সংখ্যার সামনে নীচে থেকে ফাইলের নাম গণনা করা হয়।
জিম্মিজ

7

অত্যন্ত সরল বাশ কমান্ড ব্যবহার করে একটি সমাধান এখানে দেওয়া হল।

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

অনুলিপি কমান্ড সম্পাদন করে প্রতিটি লাইনের উপরে লুপ করে।


6

যতক্ষণ আপনি শেল সাজানোর পক্ষে সম্মতিজনক তা খুঁজে পান, আপনি কেবল এটি করতে পারেন:

set -- /path/to/source/dir/*
[ "$#" -le 4 ] || shift "$(($#-4))"
cp "$@" /path/to/target/dir

এটি bashপ্রদত্ত-স্পেসিফিক অ্যারে সমাধানের সাথে খুব মিল , তবে কোনও পসিক্স-সামঞ্জস্যপূর্ণ শেলের কাছে পোর্টেবল হওয়া উচিত। উভয় পদ্ধতি সম্পর্কে কিছু নোট:

  1. আপনি আপনার cpযুক্তি ডব্লিউ / cp --বা আপনি যে কোনও .বিন্দুর মধ্যে একটি বা /প্রতিটি নামের শিরোনামে পেতে পারেন তা গুরুত্বপূর্ণ lead আপনি যদি এটি করতে ব্যর্থ হন তবে আপনি প্রথম যুক্তিতে নেতৃস্থানীয় -ড্যাশ ঝুঁকিপূর্ণ cpযা বিকল্প হিসাবে ব্যাখ্যা করা যেতে পারে এবং অপারেশনটিকে ব্যর্থ হতে পারে বা অন্যথায় অনিচ্ছাকৃত ফলাফল সরবরাহ করতে পারে।

    • এমনকি যদি বর্তমান ডিরেক্টরিটি উত্স ডিরেক্টরি হিসাবে কাজ করা হয় তবে এটি সহজে ... set -- ./*বা হিসাবে সম্পন্ন হয় array=(./*)
  2. আপনার আরগ অ্যারে কমপক্ষে যতগুলি আইটেম আপনি মুছে ফেলার চেষ্টা করছেন তা নিশ্চিত করার জন্য উভয় পদ্ধতি ব্যবহার করার সময় এটি গুরুত্বপূর্ণ - আমি এখানে একটি গণিতের বিস্তার দিয়ে তা করি। 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এগুলি অনুলিপি করার সাথে সাথে সমস্ত ফাইল নামগুলিতে স্টাইলের বিকল্প প্রয়োগ করবে।


4

যদি কেবলমাত্র ফাইল থাকে এবং তাদের নামগুলিতে শ্বেতক্ষেত্র বা নিউলাইন (এবং আপনি কোনও সংশোধন করেননি $IFS) বা গ্লোব অক্ষর (বা কিছু প্রিন্টযোগ্য অক্ষর যার কিছু প্রয়োগ রয়েছে ls) দিয়ে না শুরু করেন ., তবে আপনি এটি করতে পারেন :

cp -- $(ls | tail -n 4) ~/

একে কমান্ড সাবস্টিটিউশন বলা হয় এবং এটি সত্যই কার্যকর। tldp.org/LDP/abs/html/commandsub.html#CSPARENS
iimar

ধন্যবাদ! এটা কাজ করে। a_সমস্ত চারটি ফাইলের উপসর্গটি কীভাবে দ্রুত প্রপেন্ড করা যায়? আমি চেষ্টা করেছি echo "a_$(ls | tail -n 4)", তবে এটি কেবলমাত্র প্রথম ফাইলটিকেই সংশোধন করে।
সিবস জুয়াং

@ সিবসগাম্বলিং আমার পদ্ধতির পক্ষে এটি উপযুক্ত নয় তবে জন 1024 এর উত্তর সহজেই এর সাথে মানিয়ে নিতে পারে।
হাউক লেগেছে 26'15

5
সাধারণভাবে পার্সিং lsআউটপুটটিকে খারাপ ফর্ম হিসাবে বিবেচনা করা হয় কারণ এটি সাধারণত ফাইলের নামগুলিতে মারাত্মকভাবে ব্যর্থ হয় যা কেবলমাত্র ফাঁকা স্থান নয়, তবে ট্যাব, নিউলাইনগুলি বা অন্যান্য বৈধ তবে "কঠিন" অক্ষরও রাখে।
এইচবিউইজন

2
@ হককিজিং যদিও এটি বর্তমানে কোনও সমস্যা না হলেও (কারণ আমার ডিরেক্টরিতে আমার "জটিল" ফায়ারনাম নেই) তবে আমার 2 বছরের মধ্যে থাকতে পারে এবং হঠাৎ জিনিস আমার পায়ে পড়ে যায় ...
গিগলগল

1

এটি কোনও লুপ কোড ছাড়াই একটি সহজ বাশ সমাধান। বর্তমান দির থেকে শেষ 4 টি ফাইল গন্তব্যে অনুলিপি করুন:

$ find . -maxdepth 1 -type f |tail -n -4|xargs cp -t "$destdir"

1
আপনি কীভাবে নিশ্চিত হন যে findএটি আপনাকে পছন্দসই ক্রমে ফাইলগুলি দেয়? আপনি কীভাবে নিশ্চিত করতে পারেন যে তাদের নামগুলিতে হোয়াইটস্পেস অক্ষরযুক্ত ফাইলগুলি (নিউলাইনগুলি সহ) সঠিকভাবে পরিচালনা করা হয়েছে?
Kusalananda
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.