ইউনিক্স শেল স্ক্রিপ্টিং: পুনরাবৃত্তভাবে কীভাবে একটি ডিরেক্টরিতে ফাইল সরানো যায়?


8

আমার কাছে প্রচুর পরিমাণে ছোট ছোট ফাইল রয়েছে, এফ, যেমন ডিরেক্টরি কাঠামোয় সাজানো থাকে:

/A/B/C/f

এ স্তরে 11 টি ডিরেক্টরি রয়েছে, বি এর স্তরে প্রায় 100 টি ডিরেক্টরি সহ প্রতিটি সি এর স্তরে প্রায় 30 টি ডিরেক্টরি সহ প্রতিটি ফাইল একটি এফ সহ।

আমি কীভাবে সমস্ত ফাইলকে এক স্তর উপরে নিয়ে যেতে পারি? উদাহরণস্বরূপ, ফাইলগুলির এই সেটটি দেওয়া ...

/ এ / বি / সি / এফ 1 / এ / বি / সি / এফ 2
/ এ / বি / সি
/ এফ 3
/ এ / বি / সি / এফ 4

আমি ডিরেক্টরিটিতে /A/B/4 ফাইল, এফ 1 এর মাধ্যমে এফ 4 রাখতে চাই । ডিরেক্টরি সি মুছে ফেলার প্রয়োজন হয় না।

আমি এই একটি মীমাংসিত সমস্যা আশা করছি, সম্ভবত জড়িত find, xargsএবং whatnot। কোন ধারনা?

চিয়ার্স,

জেমস

উত্তর:


9

এটি জিএনইউ অনুসন্ধান (লিনাক্সে যেমন পাওয়া যায়) বা সমর্থন করে এমন অন্য কোনও সন্ধানের সাথে মোটামুটি সহজ -execdir:

find A -type f -execdir mv -i {} .. \;

একটি স্ট্যান্ডার্ড সহ find:

find A -type f -exec sh -c 'mv -i "$1" "${1%/*}/.."' sh {} \;

Zsh সহ:

zmv -Q -o-i 'A/(**/)*/(*)(.)' 'A/$1$2'

যদি ডিরেক্টরি কাঠামোর সর্বদা নেস্টিং স্তর থাকে তবে আপনার কোনও পুনরাবৃত্ত ট্র্যাভারসাল প্রয়োজন নেই (তবে প্রথমে খালি ডিরেক্টরিগুলি সরিয়ে দিন):

for x in */*; do; echo mv -i "$x"/*/* "$x"/..; done

1

ফাইলগুলির সেটের জন্য, এটি করবে:

$ cd /A/B/C/
$ mv ./* ../

তবে আমি আশা করছি যে আপনার সমস্যাটি আরও জটিল হয়ে উঠছে ... আমি এর উত্তর দিতে পারব না ... আপনার দির কাঠামোটি কেমন তা আমি যথেষ্ট নিশ্চিত নই ... আপনি কি পরিষ্কার করে বলতে পারবেন?


এটি স্পষ্টতই যে কোনও একটি ডিরেক্টরি / এ / বি / সি এর জন্য কাজ করবে, তবে আমার প্রায় 30000 এর মতো ডিরেক্টরি রয়েছে বলে আমি আশা করছি যে কমান্ডটি হায়ারার্কির শীর্ষে কার্যকর করা যেতে পারে সেগুলি একবারে দেখাতে পারে।
jl6

1
@ jl6 আমি দেখতে পাচ্ছি, এবং কেবল ফাইলগুলিতে চলন দরকার? সুতরাং সি-তে বি-তে চলে যাবে না, এবং খ-এ-তে হবে না, ইত্যাদি ...
স্ট্যাক ওভারফ্লো মারা গেছে

এটি সঠিক - ক্রিয়াকলাপটি কেবল ফাইলে করা উচিত, স্তরক্রমের সর্বনিম্ন স্তরে, এবং সেগুলি কেবলমাত্র এক স্তর উপরে সরানো উচিত।
jl6

0

আমার প্রথম অনুমান

$ find A -type f -exec mv {} .. \;  

যতক্ষণ আপনি নির্দিষ্ট -depthনা করেন ঠিক আছে। আমি এটি চেষ্টা করে দেখিনি তাই এটির প্রতিশ্রুতি দেওয়ার আগে প্রথমে এটি পরীক্ষা করুন।


একই নামে দুটি ফাইল বুদ্ধিমান হলে কী করতে পারে?

অনুসন্ধান করুন সমস্যা নয়, এম্বেড করা "এমভি" কমান্ডটি। ডুপির নামগুলি ভাল হবে না কারণ এমভি নতুন নামকরণ করবে না, এটি ওভাররাইট হতে চলেছে। আপনি সামান্য সাহায্যের জন্য mv -i ব্যবহার করতে পারেন, তবে 30,000+ ফাইল সহ যা বেদনাদায়ক হতে পারে। আপনার যদি পরিস্থিতির উপর এতটা নিয়ন্ত্রণের প্রয়োজন হয় তবে আপনার কোনও স্ক্রিপ্টিং ভাষায় লিখিত প্রোগ্রামের প্রয়োজন হতে পারে (আমার পছন্দটি পাইথন, ওয়াইএমএমভি) হবে।
hotei

আমি এমভি সহ "ব্যাকআপ" ব্যবহার করি নি, তবে ম্যান পৃষ্ঠাটি দেখে মনে হচ্ছে এটি আপনার দুপ নামের সমস্যার সমাধান হতে পারে। "A -type f -exec mv সন্ধান করুন - ব্যাকআপ নম্বরযুক্ত {} .. \;" কাজ করতে পারে (নোট এটি
ব্যাকআপ

প্রদত্ত অনুসন্ধানের উদাহরণটি নীচের স্তরের সমস্ত ফাইলকে এ এর ​​উপরে একটি ডিরেক্টরিতে নিয়ে যাবে (আমি বিশ্বাস করি ".." সন্ধান দ্বারা / এমভি পাস করার আগে শেল দ্বারা ব্যাখ্যা করা হচ্ছে?) শ্রেণিবিন্যাসের মাত্র এক স্তর উপরে যেতে আমার ফাইলগুলি দরকার। আরও একটি স্পেসিফিকেশন: ফাইলগুলি কেবল এক স্তরকে সরিয়ে নিলে কোনও নকল ফাইলের নাম থাকবে না।
jl6

@ হোটেই: mvবর্তমান ডিরেক্টরিতে কমান্ডগুলি কার্যকর করা হয়, তাই ..আপনি যা আশা করেন তা করেন না। সমাধানের জন্য আমার উত্তর দেখুন । @ jl6: শেলটির কোনও সম্পর্ক নেই .., এটি কার্নেল দ্বারা পরিচালিত।
গিলস 'দুষ্ট হওয়া বন্ধ করুন'

0

আপনি শুধুমাত্র যে গাছের পাতা ডিরেক্টরি হয় (অর্থাত আপনি স্থানান্তর করতে না চান ফাইল স্থানান্তর করার জন্য চান /A/B/fileকরতে /Aযদি Bসাবডিরেক্টরি রয়েছে) তারপর এখানে উপায়ে তা করতে একটি দম্পতি আছে:

উভয়েরই এটি প্রয়োজন require

leaf ()
{
    find $1 -depth -type d | sed 'h; :b; $b; N; /^\(.*\)\/.*\n\1$/ { g; bb }; $ {x; b}; P; D'
}
shopt -s nullglob

এই এক কাজ করে:

leaf A | while read -r dir
do
    for file in "$dir"/*
    do
        parent=${dir%/*}
        if [[ -e "$parent/${file##*/}" ]]
        then
            echo "not moved: $file"
        else
            mv "$file" "$parent"
        fi
    done
done

এটি দ্রুত হবে তবে এটি খালি উত্স ডিরেক্টরি পছন্দ করে না:

leaf A | while read -r dir
do
    mv -n "${dir}"/* "${dir%/*}"
    remains=$(echo "$dir"/*)
    [[ -n "$remains" ]] && echo "not moved: $remains"
done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.