অনুলিপি ছাড়াই লিনাক্সে 2 ডিরেক্টরি গাছ মার্জ করবেন?


35

আমার অনুরূপ লেআউট সহ দুটি ডিরেক্টরি গাছ রয়েছে

.
 |-- dir1
 |   |-- a
 |   |   |-- file1.txt
 |   |   `-- file2.txt
 |   |-- b
 |   |   `-- file3.txt
 |   `-- c
 |       `-- file4.txt
 `-- dir2
     |-- a
     |   |-- file5.txt
     |   `-- file6.txt
     |-- b
     |   |-- file7.txt
     |   `-- file8.txt
     `-- c
         |-- file10.txt
         `-- file9.txt

আমি dir1 এবং dir2 ডিরেক্টরি গাছগুলি তৈরি করতে মার্জ করতে চাই:

 merged/
 |-- a
 |   |-- file1.txt
 |   |-- file2.txt
 |   |-- file5.txt
 |   `-- file6.txt
 |-- b
 |   |-- file3.txt
 |   |-- file7.txt
 |   `-- file8.txt
 `-- c
     |-- file10.txt
     |-- file4.txt
     `-- file9.txt

আমি জানি যে আমি "সিপি" কমান্ডটি ব্যবহার করে এটি করতে পারি, তবে আমি অনুলিপি না করে ফাইলগুলি সরাতে চাই, কারণ প্রকৃত ডিরেক্টরিগুলি যা আমি মার্জ করতে চাই তা সত্যই বড় এবং এতে প্রচুর ফাইল (মিলিয়ন) থাকে। আমি যদি "এমভি" ব্যবহার করি তবে আমি বিরোধী ডিরেক্টরি নামের কারণে "ফাইল বিদ্যমান" ত্রুটি পেয়েছি।

আপডেট: আপনি ধরে নিতে পারেন যে দুটি ডিরেক্টরি গাছের মধ্যে কোনও সদৃশ ফাইল নেই।


আপনি কি নিশ্চিত যে দুটি ফোল্ডারের মধ্যে ফাইলের নামের কোনও সদৃশ নেই? ডুপ্লিকেট থাকলে আপনি কি হতে চান?
জোড়দাচে

আক্ষরিক অর্থে যদি আপনার একক ডিরেক্টরিতে কয়েক মিলিয়ন ফাইল থাকে তবে আপনার পারফরম্যান্সের কারণে ফাইলগুলি পৃথক সাব ডিরেক্টরিতে বিভক্ত করা উচিত - যদিও এটি জিজ্ঞাসিত প্রকৃত প্রশ্নের তুলনায় অপ্রাসঙ্গিক।
DrStalker

উত্তর:


28
rsync -ax --link-dest=dir1/ dir1/ merged/
rsync -ax --link-dest=dir2/ dir2/ merged/

এই বরং তাদের চলন্ত চেয়ে hardlinks তৈরি করবে, আপনি যাচাই করতে পারেন যে, তারা সঠিকভাবে, তারপর, অপসারণ সরানো হয়েছে dir1/এবং dir2/


9
ধরনের। এটি আসলে কোনও ডিস্ক ব্যবহার নকল করে না, এটি কেবল একই ডিস্কের অন্য একটি পয়েন্টার তৈরি করে এবং আসলে কোনও তথ্যই 'অনুলিপি' করে না। ( এন.ইইউইকিপিডিয়া.org / উইকি / হার্ড_লিঙ্কগুলি দেখুন ) তবে ফাইলের জন্য একবারে এই অপারেশনটি করতে হবে। আপনি কেবল একটি ডিরেক্টরিকে স্থানান্তরিত করতে পারবেন না বলে এই উত্তরগুলি সমস্তই বায়ু সঞ্চারিত হয়।
ক্রিস্টোফার কারেল

1
যেহেতু ফাইলগুলি অনুলিপি করার ক্ষেত্রে এটির ওভারহেড নেই, এটি সঠিকভাবে গ্রহণযোগ্য সমাধান।
টুবু

2
এটি কেবল যদি একই ফাইল সিস্টেমে থাকে তবে এটি কাজ করে। যদি তারা একই ফাইল সিস্টেমে থাকে তবে মুছুন বিকল্পের সাথে আরএসআইএনসি কি কোনও পদক্ষেপ নেবে? (এর অর্থ, কেবল ডিরেক্টরি তথ্য পরিবর্তন করুন, তবে ফাইলটি সরান না)।
রোনাল্ড পটল

1
rsync অনুলিপি করবে, তারপরে যদি এটি ফাইল সিস্টেমগুলিকে অনুসরণ করে তবে মুছুন।
কর্মক্ষেত্র

5
একটি সতর্কতামূলক: --link-destপথটি নিখুঁত করুন, বা এর সাথে তুলনামূলক করুন merged/; অথবা এটি অনুলিপি করবে।
টুবু

21

এটি আশ্চর্যের বিষয় নয় যে cpএর বিকল্প রয়েছে -l:

-লি, - লিঙ্ক
       অনুলিপি পরিবর্তে হার্ড লিঙ্ক ফাইল

আপনি যেমন কিছু করতে পারেন

% এমকেডির মার্জ
% cp -rl dir1 / * dir2 / * মার্জ করুন
% rm -r দির *
% গাছ একীকরণ 
একত্রীকরণ
├── ক
1 ├── file1.txt
। ├── file2.txt
। 5 file5.txt
। └── file6.txt
├── খ
। ├── file3.txt
। ├── file7.txt
8 8 file8.txt
└── গ
    10 file10.txt
    4 file4.txt
    9 file9.txt

13 ডিরেক্টরি, 0 ফাইল

এটি বিভিন্ন হার্ড ড্রাইভ জুড়ে কাজ করে না ...
অ্যালেক্স লিচ

4
এটি বলাই আরও সঠিক যে এটি ফাইল সিস্টেমগুলিতে কাজ করে না, কারণ ফাইল সিস্টেমগুলি একাধিক হার্ড ড্রাইভ জুড়ে বিস্তৃত হতে পারে। এছাড়াও, যদি ওপ চাচ্ছে তবে ফাইলগুলি অনুলিপি করা এড়ানো উচিত, এটি ভাল জিনিস যা cp -lফাইল সিস্টেমগুলিতে কাজ করে না।
lvella

2
ফাইলের সমস্ত বৈশিষ্ট্য রাখতে এবং নিম্নলিখিত চিহ্নগুলি এড়াতে cp -aআপনি (প্রতিশব্দ প্রতিশব্দ cp -RPp) ব্যবহার করতে চাইতে পারেন : এখানে আদেশটি হয়ে যায় cp -al dir1/* dir2/* merge
ট্রাইসেস

5

তার জন্য আপনি নাম পরিবর্তন করতে পারেন (ওরফে পূর্ব নাম, পার্ল প্যাকেজ থেকে)। সাবধান থাকুন যে নামটি অগত্যা ডেবিয়ান / উবুন্টুর বাইরে আমি যে কমান্ডটি বর্ণনা করেছি তা উল্লেখ করে না (যদিও এটি আপনার প্রয়োজন হলে এটি একক পোর্টেবল পার্ল ফাইল)।

mv -T dir1 merged
rename 's:^dir2/:merged/:' dir2/* dir2/*/*
find dir2 -maxdepth 1 -type d -empty -delete

আপনার কাছে ভিডির ব্যবহারের বিকল্প রয়েছে (মর্টিল থেকে) এবং আপনার পছন্দের পাঠ্য সম্পাদক থেকে ফাইল পাথ সম্পাদনা করতে পারেন।


3

আমি rsync এবং prename সমাধান, কিন্তু যদি আপনি সত্যিই করতে চাই এমভি কাজ এবং

  • আপনার সন্ধান জানে -print0এবং -depth,
  • তোমার এক্সারগস জানে -0,
  • আপনার প্রিন্টফ আছে ,

তারপরে বোর্ন-স্টাইলের শেল স্ক্রিপ্ট সহ, প্রচুর সংখ্যক ফাইলের নাম যেমন র্যান্ডম হোয়াইটস্পেস থাকতে পারে তা হ্যান্ডেল করা সম্ভব:

#!/bin/sh

die() {
    printf '%s: %s\n' "${0##*/}" "$*"
    exit 127
}
maybe=''
maybe() {
    if test -z "$maybe"; then
        "$@"
    else
        printf '%s\n' "$*"
    fi
}

case "$1" in
    -h|--help)
        printf "usage: %s [-n] merge-dir src-dir [src-dir [...]]\n" "${0##*/}"
        printf "\n    Merge the <src-dir> trees into <merge-dir>.\n"
        exit 127
    ;;
    -n|--dry-run)
        maybe=NotRightNow,Thanks.; shift
    ;;
esac

test "$#" -lt 2 && die 'not enough arguments'

mergeDir="$1"; shift

if ! test -e "$mergeDir"; then
    maybe mv "$1" "$mergeDir"
    shift
else
    if ! test -d "$mergeDir"; then
        die "not a directory: $mergeDir"
    fi
fi

xtrace=''
case "$-" in *x*) xtrace=yes; esac
for srcDir; do
    (cd "$srcDir" && find . -print0) |
    xargs -0 sh -c '

        maybe() {
            if test -z "$maybe"; then
                "$@"
            else
                printf "%s\n" "$*"
            fi
        }
        xtrace="$1"; shift
        maybe="$1"; shift
        mergeDir="$1"; shift
        srcDir="$1"; shift
        test -n "$xtrace" && set -x

        for entry; do
            if test -d "$srcDir/$entry"; then
                maybe false >/dev/null && continue
                test -d "$mergeDir/$entry" || mkdir -p "$mergeDir/$entry"
                continue
            else
                maybe mv "$srcDir/$entry" "$mergeDir/$entry"
            fi
        done

    ' - "$xtrace" "$maybe" "$mergeDir" "$srcDir"
    maybe false >/dev/null ||
    find "$srcDir" -depth -type d -print0 | xargs -0 rmdir
done

আপনি xargs এর ইনপুটটিকে নতুন লাইনে সীমিত করতে এবং অনুবাদটি এড়িয়ে যেতে বলতে পারেন। উদাহরণস্বরূপ নিম্নলিখিতটি বর্তমান ডিরেক্টরিতে আপনার সমস্ত টরেন্ট ফাইলগুলি এবং এমনকি ইউনিকোড অক্ষর বা কিছু অন্যান্য টমফুলারি সহ মুছে ফেলবে। find . -name '*.torrent' | xargs -d '\n' rm
PRS

2

পাশবিক বল bash

#! /bin/bash

for f in $(find dir2 -type f)
do
  old=$(dirname $f)
  new=dir1${old##dir2}
  [ -e $new ] || mkdir $new
  mv $f $new
done

পরীক্ষা এটা করে

# setup 
for d in dir1/{a,b,c} dir2/{a,b,c,d} ; do mkdir -p $d ;done
touch dir1/a/file{1,2} dir1/b/file{3,4} dir2/a/file{5,6} dir2/b/file{7,8} dir2/c/file{9,10} dir2/d/file11

# do it and look
$ find dir{1,2} -type f
dir1/a/file1
dir1/a/file2
dir1/a/file5
dir1/a/file6
dir1/b/file3
dir1/b/file7
dir1/b/file8
dir1/c/file4
dir1/c/file9
dir1/c/file10
dir1/d/file11

2
ওপি লক্ষ লক্ষ ফাইল উল্লেখ করেছে, যা সম্ভবত এই নির্মাণকে ভেঙে ফেলবে। এছাড়াও, এটি স্পেস, নিউলাইনস ইত্যাদির সাথে ফাইলের নামগুলি সঠিকভাবে পরিচালনা করবে না
ক্রিস জনসন

0

উন্নয়নের বিভিন্ন পর্যায়ে উত্স কোড গাছের জন্য আমাকে বেশ কয়েকবার এটি করতে হয়েছিল। আমার সমাধানটি ছিল নিম্নলিখিত পদ্ধতিতে গিটকে ব্যবহার করা:

  1. একটি গিট সংগ্রহস্থল তৈরি করুন এবং dir1 থেকে সমস্ত ফাইল যুক্ত করুন।
  2. সমর্পণ করা
  3. Dir2 থেকে সমস্ত ফাইল সরান এবং ফাইলগুলিতে অনুলিপি করুন
  4. সমর্পণ করা
  5. দুটি কমিট পয়েন্টের মধ্যে পার্থক্য দেখুন এবং আমি কীভাবে ফলাফলগুলিকে মার্জ করতে চাই সে সম্পর্কে সতর্কতা অবলম্বন করুন।

আপনি এটিকে আরও শাখার মাধ্যমে জরিমানা করতে পারেন তবে এটি সাধারণ ধারণা। এবং আপনার এটি স্টাফিং সম্পর্কে কম ভয় রয়েছে কারণ আপনার কাছে প্রতিটি রাজ্যের সম্পূর্ণ স্ন্যাপশট রয়েছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.