एमवी के साथ फ़ोल्डर्स विलय?


149

यदि मैं mv"फ़ोल्डर" नामक फ़ोल्डर को एक निर्देशिका में स्थानांतरित करने के लिए उपयोग करता हूं जिसमें पहले से "फ़ोल्डर" शामिल है, तो क्या वे विलय करेंगे या इसे प्रतिस्थापित किया जाएगा?

जवाबों:


120

mvनिर्देशिकाओं को मर्ज या अधिलेखित नहीं कर सकते, यह "mv:" a 'को' b 'में नहीं ले जा सकता: संदेश को खाली नहीं कर सकता "निर्देशिका खाली नहीं है , तब भी जब आप --forceविकल्प का उपयोग कर रहे हों ।


आप इस का उपयोग करते हुए अन्य उपकरणों (जैसे आस-पास काम कर सकते हैं rsync, findया यहां तक कि cp), लेकिन आप ध्यान से प्रभाव पर विचार करने की जरूरत है:

  • rsyncएक निर्देशिका की सामग्री को दूसरे में विलय कर सकते हैं (आदर्श रूप से --remove-source-files1 विकल्प के साथ केवल उन स्रोत फ़ाइलों को सुरक्षित रूप से हटाने के लिए जिन्हें सफलतापूर्वक स्थानांतरित किया गया था, और -aयदि आप चाहें तो सामान्य अनुमति / स्वामित्व / समय संरक्षण विकल्प के साथ
    ... लेकिन यह एक पूर्ण प्रतिलिपि कार्रवाई है , और इसलिए बहुत डिस्क-गहन हो सकते हैं।
  • वर्तमान में पसंद का विकल्प: आप को जोड़ सकते हैं rsyncके --link-dest=DIRविकल्प और (को कॉपी फ़ाइल सामग्री, जहां संभव के बजाय hardlinks बनाने के लिए) --remove-source-filesएक अर्थ बहुत एक नियमित रूप से करने के लिए इसी तरह की प्राप्त करने के लिए mv
    इसके --link-destलिए स्रोत निर्देशिका (या गंतव्य से स्रोत के लिए एक रिश्तेदार पथ ) को एक पूर्ण पथ दिया जाना चाहिए ।
    ... लेकिन यह --link-destअनपेक्षित तरीके से उपयोग किया जा रहा है (जो जटिलताओं का कारण हो सकता है या नहीं भी हो सकता है), स्रोत के लिए निरपेक्ष पथ को जानने (या निर्धारित करने) की आवश्यकता है (एक तर्क के रूप में --link-dest), और फिर से खाली निर्देशिका संरचना को साफ करने के लिए छोड़ देता है। प्रति 1
  • आपfind लक्ष्य पर स्रोत निर्देशिका संरचना को क्रमिक रूप से पुन: उपयोग करने के लिए उपयोग कर सकते हैं , फिर व्यक्तिगत रूप से वास्तविक फ़ाइलों को स्थानांतरित कर सकते हैं
    ... लेकिन इसके लिए कई बार स्रोत से पुनरावृत्ति करनी होगी और दौड़ की स्थितियों (बहु-चरणीय प्रक्रिया के दौरान स्रोत पर बनाई जा रही नई निर्देशिकाओं) का सामना कर सकते हैं )
  • cpहार्ड लिंक बना सकते हैं (बस उसी मौजूदा फ़ाइल के लिए अतिरिक्त संकेत), जो एक विलय के समान परिणाम बनाता है mv(और केवल बिंदु बनाए जाने के बाद से बहुत ही IO- कुशल है और कोई वास्तविक डेटा कॉपी नहीं किया जाना चाहिए)
    ... लेकिन यह फिर से एक संभावित दौड़ की स्थिति से पीड़ित होता है (स्रोत में नई फाइलें हटा दी जा रही हैं, हालांकि वे पिछले चरण में कॉपी नहीं किए गए थे)

इनमें से कौन सा वर्कअराउंड (यदि कोई है) उपयुक्त है तो यह आपके विशिष्ट उपयोग के मामले पर बहुत निर्भर करेगा।
हमेशा की तरह, इनमें से किसी भी कमांड को निष्पादित करने से पहले सोचें, और बैकअप लें।


1: ध्यान दें कि rsync --remove-source-filesकोई भी निर्देशिका नहीं हटेगी, इसलिए आपको find -depth -type d -empty -deleteखाली स्रोत निर्देशिका पेड़ से छुटकारा पाने के लिए बाद में कुछ करना होगा ।


ऐसा लगता है कि आपने केवल एक कार्यान्वयन की कोशिश की है mv। यह उत्तर एक व्यापक सत्य के साथ बेहतर होगा। लिनक्स, बीएसडी और "वास्तविक" यूनिक्स, या पोसिक्स या एसयूएस से एक संदर्भ।
वॉरेन यंग

@WarrenYoung आप सही हैं, मैं सिर्फ कोशिश की mvडेबियन द्वारा प्रयोग किया जाता कार्यान्वयन - जोर पर होने की कोशिश की , जब से मैनपेज इस व्यवहार का उल्लेख नहीं है ...
n.st

38
Rsync का नुकसान यह है कि यह वास्तव में डेटा को कॉपी करता है, केवल हार्ड लिंक को बदलने के बजाय, जो कि संभावित संसाधन गहन है यदि आप बहुत अधिक डेटा के साथ काम कर रहे हैं।
जोनाथन मेयर

7
@Keith ध्यान दें कि गंतव्य निर्देशिका में--delete केवल उन फ़ाइलों को हटाता है जो स्रोत निर्देशिका में मौजूद नहीं हैं।
n।

1
@JonathanMayer rsync कई हार्ड लिंक संबंधित सुविधाओं के रूप में है। उदाहरण के लिए, आप केवल -Hफ़ंक्शन के साथ हार्ड लिंक को संरक्षित कर सकते हैं या आप गंतव्य का उपयोग करके फ़ाइलों को हार्डलिंक कर सकते हैं --link-dest। हालांकि उनका उपयोग करने से पहले मैन पेज देखें।
एलो

87
rsync -av /source/ /destination/
(after checking)
rm -rf /source/

यह n.st द्वारा टिप्पणी की तरह स्रोत फ़ाइलों को हटा देगा?
डोमिनिक

3
नहीं, मैं सुरक्षा कारणों से इसे दो चरणों में बनाना पसंद करूंगा। विलय और हटाया गया स्रोत अपरिवर्तनीय है। N.st awer में Additon स्टेप (निर्देशिकाओं को हटाने के लिए) की आवश्यकता है।
फ़ैज़ी

3
--remove-source-filesकेवल उन फ़ाइलों को हटाने का लाभ है, जिन्हें सफलतापूर्वक स्थानांतरित किया गया था, इसलिए आप findखाली निर्देशिकाओं को हटाने के लिए उपयोग कर सकते हैं और उन सभी चीज़ों के साथ छोड़ दिया जाएगा जिन्हें बिना rsyncs जाँच के स्थानांतरित नहीं किया गया था ।
n.st

4
लेकिन यह वास्तव में आगे नहीं बढ़ रहा है - गति प्रभाव बहुत बड़ा है, यदि बड़ी फाइलें शामिल हैं।
एलेक्स

लेकिन आप वास्तव में शुद्ध कदम और विलय नहीं कर सकते।
फाज़ी

64

आप cp कमांड के -lविकल्प का उपयोग कर सकते हैं , जो पूर्ण-डेटा प्रतियों के बजाय एक ही फाइल सिस्टम पर फ़ाइलों की हार्ड लिंक बनाता है । निम्न आदेश फ़ोल्डर को पैरेंट फ़ोल्डर ( ) में कॉपी करता है जिसमें पहले से ही नाम के साथ एक निर्देशिका है ।source/folderdestinationfolder

cp -rl source/folder destination
rm -r source/folder

तुम भी उपयोग कर सकते हैं -P( --no-dereferenceया - डी-संदर्भ सांकेतिक लिंक नहीं है) -a( --archive-, सभी मेटाडाटा को संरक्षित भी शामिल है -Pअपनी आवश्यकताओं पर निर्भर करता है विकल्प),।


7
@rautamiekka: मुझे लगता है कि आप हार्ड लिंक का उपयोग करने का कारण पूछ रहे हैं। यदि आप नहीं जानते कि कड़ी क्या हैं और आपको उनका उपयोग क्यों करना चाहिए, तो आपको शायद यह मार्ग नहीं अपनाना चाहिए। हालाँकि, हार्ड लिंक बनाना पूर्ण प्रतिलिपि नहीं करता है, इसलिए यह ऑपरेशन पूर्ण प्रतिलिपि की तुलना में कम समय के लिए परिमाण का आदेश लेगा। और, आप सॉफ्ट लिंक के बजाय हार्ड लिंक का उपयोग करेंगे ताकि आप स्रोत फ़ाइलों को हटा सकें और फिर भी अमान्य डेटा को इंगित करने के बजाय सही डेटा हो। और cpबजाय इसके कि rsyncहर प्रणाली के पास है cpऔर सभी के पास परिचित है।
पाल्सीम

7
स्वीकार किए जाते हैं जवाब नहीं होने के लिए इस समाधान की प्रतिभा को देखा जा सकता है। यह एक सुरुचिपूर्ण समाधान है। आप cpके संचालन समय के साथ मर्ज की क्षमता मिलती है mv
TheHerk

2
यदि आप जानते हैं कि आपको उन फ़ाइलों को स्थानांतरित करने की आवश्यकता नहीं है जो पहले से ही गंतव्य पर मौजूद हैं जिन्हें आप भी जोड़ना चाहते हैं-n
ndemou

1
@Ruslan: यह सच है, लेकिन आप किसी भी विधि के साथ फाइल सिस्टम में कॉपी के बिना नहीं जा सकते। यहां तक ​​कि mv /fs1/file /fs2/(फाइलसिस्टम के पार) एक कॉपी करेगा और फिर डिलीट करेगा।
पलसीम

2
सही है, लेकिन जब mvतक "कुशलता से" (जो लक्ष्य अभी तक मौजूद नहीं है, बशर्ते कि) "कुशलतापूर्वक" या जिसे आप इसे कहते हैं, cp -rlवह विफल हो जाएगा।
रुस्लान

23

मैं इन चार चरणों की सिफारिश करूंगा:

cd ${SOURCE}; 
find . -type d -exec mkdir -p ${DEST}/\{} \; 
find . -type f -exec mv \{} ${DEST}/\{} \; 
find . -type d -empty -delete

या बेहतर अभी तक, यहाँ एक स्क्रिप्ट है जो शब्दार्थ को समान करती है mv:

#!/bin/bash

DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"

for SRC in ${@:1:$((${#@} -1))}; do   (
    cd "$SRC";
    find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
    find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
    find . -type d -empty -delete
) done

आर्ग्स SOURCE, DEST
schuess

यह काफी उपयोगी लगता है। मैं अपनी हार्ड ड्राइव को साफ करने के लिए इसका उपयोग करने के लिए परीक्षा में हूँ क्या कोई अन्य विशेषज्ञ इस स्क्रिप्ट पर बैकअप का एक गुच्छा सौंपने से पहले इस पर टिप्पणी कर सकते हैं? :-)
लार्स

BTW, यदि आप rsync -u(केवल अद्यतन अगर नया) के बराबर करना चाहते थे , mv(कुछ संस्करणों में कम से कम) भी -uविकल्प ले सकते हैं । हालाँकि, उस स्थिति में आप गैर-रिक्त स्रोत निर्देशिकाओं को हटाना चाहते हैं और साथ ही खाली भी कर सकते हैं, उन मामलों को कवर करने के लिए जहां स्रोत के पेड़ की फाइलें नई नहीं हैं। @ शुक्राणु: ऐसा लगता है कि यदि आवश्यक हो तो कई स्रोत तर्क हो सकते हैं।
लार्स

1
यह व्हाट्सएप को अच्छी तरह से हैंडल नहीं करता है। मैंने इसे कुछ निर्देशिकाओं के साथ उनमें स्थान देने की कोशिश की और अनंत निर्देशिकाओं की एक अनंत श्रृंखला के साथ समाप्त किया।
रॉफर

16

यहां एक तरीका है जो निर्देशिकाओं को मर्ज करेगा। यह rsync की तुलना में बहुत तेज़ है क्योंकि यह फ़ाइलों को कॉपी करने के बजाय केवल उनका नाम बदल देता है और फिर उन्हें हटा देता है।

cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'

यह दिलचस्प है, लेकिन केवल इस विषय के लिए प्रासंगिक है और यह भी दूर नहीं है कि उपयोगकर्ता ने इसके बारे में क्या पूछा है।
शादुर

17
वास्तव में, ज्वेल का कोड वही करता है जो उपयोगकर्ता ने गुम निर्देशिका बनाने के अपवाद के साथ मांगा था। शायद आपको फिर से देखना चाहिए?
जोनाथन मेयर

3
मैं "-00" को खोजने के लिए और "-0" का उपयोग xargs में करना चाहूंगा क्योंकि ऐसी फाइलें हैं जिनके नाम में स्थान हैं। इसके अलावा, एक छोटी सी समस्या है, अगर एक नाम में कोष्ठक शामिल हैं जो वे स्थानांतरित नहीं होने जा रहे हैं।
अंकुश

2
यह छोटी संख्या की फ़ाइलों के लिए rsync की तुलना में बहुत तेज़ है, लेकिन यह हर फ़ाइल के लिए एक नई प्रक्रिया की मांग करता है, इस प्रकार यह प्रदर्शन बड़ी संख्या में छोटी फ़ाइलों के साथ संक्षिप्त है। @ पलसीम का जवाब इस समस्या से ग्रस्त नहीं है।
b0fh

2
यदि destयह पहले से ही उसी नाम से एक निर्देशिका है , तो कमांड विफल हो जाएगी source। और फ़ाइलों को एक में ले जाया जाएगा dest, जो कि अंदर है source। कमांड कुछ ज्यादा नहीं करता हैmv source/* source/dest/.
छत

3

इसे पूरा करने का एक तरीका यह होगा:

mv folder/* directory/folder/
rmdir folder

जब तक कोई दो फाइलों में एक ही नाम है folderऔर directory/folder, आप विलय यानी एक ही परिणाम प्राप्त करेंगे।


3
कैसे rm folderकाम करता है ?
जेकगोल्ड

5
@JakeGould बिलकुल नहीं। :)
n.st

rm folder -fRहमेशा मेरे लिए काम करता है
ऑक्टोपस

2
ध्यान रखें कि यह छिपी हुई फाइलों के लिए काम नहीं करेगा
b0fh

2

शुद्धतम प्रतियों के लिए, मैं टार (-) बी ब्लॉकेड कॉपी विधि का उपयोग करता हूं।

उदाहरण, स्रोत पथ के भीतर (यदि आवश्यक हो तो 'सीडी'):

tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)

यह मालिक और अनुमतियों के साथ स्रोत पेड़ की एक सटीक प्रतिलिपि बनाता है। और यदि लक्ष्य फ़ोल्डर मौजूद है, तो डेटा विलय कर दिया जाएगा। केवल पहले से मौजूद फ़ाइलों को अधिलेखित कर दिया जाएगा।

उदाहरण:

 $ cd /data1/home
 $ tar cBf - jdoe | (cd /data2/home ; tar xBf -)

जब प्रतिलिपि कार्रवाई सफल होती है, तो आप स्रोत ( rm -rf <source>) हटा सकते हैं । बेशक यह एक सटीक कदम नहीं है: डेटा को कॉपी किया जाएगा, जब तक आप स्रोत को हटा नहीं देते।

विकल्प के रूप में आप वर्बोज़ हो सकते हैं (स्क्रीन पर फ़ाइल की प्रतिलिपि बनाई जा रही है), -v के साथ: tar cBvf -

  • c: सृजन करना
  • B: पूरा ब्लॉक पढ़ें (पाइप रीड के लिए)
  • v: क्रिया
  • f: लिखने के लिए फ़ाइल
  • x: अर्क
  • -: स्टडआउट / स्टडिन

sourcefolderभी हो सकता है *(वर्तमान फ़ोल्डर में कुछ के लिए)


f -टार को निर्दिष्ट करना आमतौर पर अनावश्यक है - डिफ़ॉल्ट को स्टडिन से पढ़ना / लिखना है जो स्टडआउट के लिए है।
मुरु

1

यहाँ एक स्क्रिप्ट है जो मेरे लिए काम करती है। मैं rsync पर mv पसंद करता हूं, इसलिए मैं गहना और जोनाथन मेयर के समाधान का उपयोग करता हूं।

#!/bin/bash

# usage source1 .. sourceN dest

length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
    pushd $SRC;
    find . -type d -exec mkdir -p ${DEST}/{} \;
    find . -type f -exec mv {} ${DEST}/{} \;
    find . -type d -empty -delete
    popd
done

यह समाधान पथ नामों से ठीक से बचता नहीं है, सावधान रहें।
user12439

@ user12439, यदि आप मुझे दिखाते हैं कि मुझे कौन सा भाग ठीक करना है तो मैं समाधान को अपडेट करूँगा।
xer0x

1

Cp या rsync जैसी कमांड का उपयोग करना एक अच्छा विचार नहीं है। बड़ी फ़ाइलों के लिए, इसमें लंबा समय लगेगा। mv बहुत तेज है क्योंकि यह केवल शारीरिक रूप से फाइलों को कॉपी किए बिना इनोड्स को अपडेट करता है। एक बेहतर विकल्प अपने ऑपरेटिंग सिस्टम के फ़ाइल प्रबंधक का उपयोग करना है। Opensuse के लिए, एक फ़ाइल प्रबंधक है जिसे Konquerer कहा जाता है। यह वास्तव में उन्हें कॉपी किए बिना फ़ाइलों को स्थानांतरित कर सकता है। इसमें विंडोज की तरह "कट एंड पेस्ट" फंक्शन है। बस निर्देशिका ए में सभी उप-निर्देशिकाओं का चयन करें और एक ही नाम के साथ उप-निर्देशिकाओं को शामिल करने वाली "निर्देशिका बी" पर क्लिक करें। यह उन्हें मर्ज कर देगा। ऐसे विकल्प भी हैं कि क्या आप एक ही नाम वाली फाइलों को अधिलेखित या नाम बदलना चाहते हैं।


1
ओपी पूछता है कि क्या होता है जब mvउपयोग किया जाता है।
दान_क्रांति

0

अजगर का हल

चूंकि मुझे एक संतोषजनक पूर्व-मौजूदा समाधान नहीं मिला, इसलिए मैंने इसे प्राप्त करने के लिए एक त्वरित पायथन स्क्रिप्ट बनाने का फैसला किया।

विशेष रूप से, यह विधि कुशल है क्योंकि यह केवल स्रोत फ़ाइल ट्री को एक बार नीचे ले जाता है।

यह आपको अपनी पसंद के हिसाब से फाइल ओवरराइटिंग जैसी चीजों को जल्दी से लाने की अनुमति देगा।

उपयोग:

move-merge-dirs src/ dest/

की सभी सामग्री चले जाएँगे src/*में dest/और src/गायब हो जाएगा।

ले जाने के मर्ज-dirs

#!/usr/bin/env python3

import argparse
import os

def move_merge_dirs(source_root, dest_root):
    for path, dirs, files in os.walk(source_root, topdown=False):
        dest_dir = os.path.join(
            dest_root,
            os.path.relpath(path, source_root)
        )
        if not os.path.exists(dest_dir):
            os.makedirs(dest_dir)
        for filename in files:
            os.rename(
                os.path.join(path, filename),
                os.path.join(dest_dir, filename)
            )
        for dirname in dirs:
            os.rmdir(os.path.join(path, dirname))
    os.rmdir(source_root)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Move merge src/* into dest. Overwrite existing files.'
    )
    parser.add_argument('src_dir')
    parser.add_argument('dest_dir')
    args = parser.parse_args()
    move_merge_dirs(args.src_dir, args.dest_dir)

गिटहब ऊपर

इसे भी देखें: https://stackoverflow.com/questions/22588225/how-do-you-merge-two-directories-or-move-with-replace-from-the-windows-command


0

यह फ़ाइलों और फ़ोल्डरों को अन्य गंतव्य पर ले जाने के लिए कमांड है:

$ mv /source/path/folder /target/destination/

याद रखें : mvयदि फ़ोल्डर b commande̲i̲n̲g m̲e willr̲ge̲d folder (यानी एक ही नाम वाला दूसरा फ़ोल्डर पहले से ही गंतव्य में मौजूद है) और d̲e̲s̲t̲i̲n̲n̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲t workt work काम नहीं करेगा ।

mv: '/ source / path / folder' को '/ target / डेस्टिनेशन / फोल्डर' में नहीं ले जा सकता है: डायरेक्टरी खाली नहीं है

यदि गंतव्य फ़ोल्डर खाली है, तो उपरोक्त आदेश ठीक काम करेगा।

तो, किसी भी मामले में दोनों फ़ोल्डरों को मर्ज करने के लिए,
या तो इसे 2 कमांड में करें:

$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder

या दोनों को एक बार के कमांड के रूप में संयोजित करें:

$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder

mv = move
cp = copy
rm = remove

निर्देशिका के लिए -r (फ़ोल्डर)
-f बल निष्पादन

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.