कैसे mv के साथ लक्ष्य फ़ाइलों को अधिलेखित करने के लिए?


154

मेरे पास एक उपनिर्देशिका है जिसमें मैं मूल निर्देशिका में जाना चाहता हूं, एक टन फाइलें और डायरियां हैं। लक्ष्य निर्देशिका में पहले से ही कुछ फाइलें और डीआईआर हैं, जिन्हें ओवरराइट करने की आवश्यकता है। केवल लक्ष्य में मौजूद फ़ाइलें अछूती छोड़ दी जानी चाहिए। क्या मैं mvऐसा करने के लिए मजबूर कर सकता हूं ? यह ( mv * ..) शिकायत करता है

mv: cannot move `xyz' to `../xyz': Directory not empty

मैं क्या खो रहा हूँ?


3
क्या आपने कोशिश की है mv -f?
साकिस

मुझे आश्चर्य है कि mv -fसही उत्तर क्यों नहीं है।
पेड्रो लोबिटो

@PedroLobito: क्योंकि यह काम नहीं करता है? -अगर केवल फाइलों को ओवरराइट करता है, लेकिन काम नहीं करता है यदि आप उपनिर्देशिका को स्थानांतरित करते हैं जो गंतव्य में मौजूद हैं और खाली नहीं हैं।
एरिकशोफर

जवाबों:


117

आपको उन्हें गंतव्य पर कॉपी करना होगा और उसके बाद स्रोत को हटाना होगा, cp -r * ..उसके बाद कमांड का उपयोग करना होगा rm -rf *

मुझे नहीं लगता कि आप निर्देशिकाओं का उपयोग करके "मर्ज" कर सकते हैं mv


4
खैर, यह वही है जो मैं नहीं करना चाहता था, क्योंकि इसमें लंबा समय लगेगा ... वैसे भी धन्यवाद।
१०:४५ पर एरिकसोफर

12
संभवतया mvतेजी से है क्योंकि आप एक ही फाइल सिस्टम पर हैं? क्या होगा यदि आप cp -lवास्तव में फ़ाइलों को स्थानांतरित करने के बजाय हार्डलिंक बनाने के लिए उपयोग करते हैं?
Mattdm

6
फ़ाइल विशेषताओं (टाइमस्टैम्प, अनुमतियां, आदि) को संरक्षित करने के लिए आपको cp -aइसके बजाय उपयोग करना चाहिए cp -r
dotancohen

2
Google के माध्यम से देर से यहाँ पहुंचने वाले लोगों के लिए, @palswim द्वारा नीचे दिया गया उत्तर mv के व्यवहार को डेटा के नए हार्ड लिंक बनाकर और फिर पुराने लिंक को हटा देता है। संक्षिप्त उत्तर cp -rl source destination && rm -r source
विलियम एवरेट

72

rsyncशायद यहाँ एक बेहतर विकल्प होगा। यह उतना ही सरल है rsync -a subdir/ ./

मेरा परीक्षण वृक्ष filename: contentsप्रारूप:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

चल रहा है rsync:

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

देता है:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

और फिर, अनुकरण करने के लिए mv, आप शायद स्रोत निर्देशिका को निकालना चाहते हैं:

$ rm -r subdir/

देते हुए:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

यदि यह गलत है, तो क्या आप वांछित परिणाम के साथ एक समान उदाहरण (उदाहरण के लिए इस उत्तर के शीर्ष से मेरे परीक्षण के पेड़ का उपयोग करके) प्रदान कर सकते हैं?


1
rsync प्रतियां। यह सवाल घूमने को लेकर है।
गाइल्स

1
@ गिल्स: धन्यवाद। मैंने rm -rइसे मूल रूप से बनाने के लिए अंत में जोड़ा mv
मिकेल

3
जब स्रोत और गंतव्य एक ही फाइल सिस्टम पर हों, तब कॉपी-तब-डिलीट एमवी के बराबर नहीं होता। mvपरमाणु है, इनोड संख्या को संरक्षित करता है (ताकि फ़ाइल खुली रह सके), और प्रतिलिपि बनाने में समय और स्थान नहीं लगता है।
गाइल्स

5
@ गिल्स: मुझे एहसास है कि, लेकिन वर्तमान में अग्रणी उत्तर है cp -r; rm -r। मुझे लगता है कि इस अर्थ में, rsyncयह भी ध्यान देने योग्य है।
मिकेल

मैंने इसे पहले ही cp / rm के साथ किया था (यह अत्यावश्यक था)। यह वास्तव में एक लंबा समय लगा। गिल्स की स्क्रिप्ट शायद बहुत तेज़ होती, लेकिन उन्हें बहुत देर हो चुकी थी।
एरिकशोफर

47

rsync--remove-source-filesपैरामीटर के साथ प्रतियों के बाद स्रोत को हटा सकते हैं । यह एक सुविधाजनक तरीका होना चाहिए जो आप करना चाहते हैं।

से rsync man page:

        --remove-source-files   sender removes synchronized files (non-dir)

यह वास्तव में सबसे अच्छा जवाब है। मैं cp -r; rmखाली जगह की कमी के कारण उपयोग नहीं कर सका । इसके बजाय rsync --remove-source-filesदोनों कम से कम इस्तेमाल किए गए डिस्क स्पेस को एक ही फाइलों पर कॉपी करने से परहेज करते हैं।
गुका

20

आप इसके साथ cpऔर कर सकते हैं rm, लेकिन भारी मात्रा में डेटा की प्रतिलिपि बनाए बिना आप (संभवतः) हस्तांतरण से बचने की कोशिश कर रहे हैं। @mattdm ने अपनी टिप्पणी में इस पर ध्यान दिया , और एक अन्य प्रश्न के उत्तर में विभिन्न विकल्पों के बारे में अधिक पूर्ण चर्चा की।

cp -rlf source destination
rm -r source

अनिवार्य रूप से, कमांड का -lविकल्प cpनई फ़ाइलों के लिए अपने डेटा को कॉपी करने के बजाय फ़ाइलों के लिए हार्ड लिंक बनाता है।


1
मुझे पता है कि ओपी ने पहले से ही अपना काम पूरा कर लिया है , जिसने इस सवाल का संकेत दिया है, लेकिन उम्मीद है कि यह उत्तर भविष्य में इस समस्या से किसी को भी मदद कर सकता है।
पलसिम

यह वास्तव में उत्तर की जरूरत है। मैंने ऐसा सिर्फ 60GB हजारों छोटी साइरस ईमेल फ़ाइलों के साथ किया और इसमें केवल 21 सेकंड का समय लगा।
लैब्राडोर

यह वह मार्ग भी है जो मैंने लिया था - मैंने इसे बस cp -al source destinationमालिक की जानकारी और अनुमतियों को संरक्षित करने के लिए बदल दिया है ।
piit79

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

@dasKeks: दरअसल, cpडिफ़ॉल्ट रूप से ओवरराइट हो जाता है। -fविकल्प फ़ाइल को हटाने के लिए (के रूप में प्रयास करता है rmनए सिरे से कॉपी करने के लिए है, जो अगर प्रक्रिया लेखन के लिए फ़ाइल नहीं खोल सकता है, हालांकि कुछ लोगों को देखने के बजाय एक त्रुटि थी पसंद करेंगे मदद कर सकते हैं, की कोशिश कर रहा से पहले)। मुझे नहीं पता कि यह ओपी के लिए मायने रखता है, लेकिन मैंने -fअपने जवाब में ध्वज को वैसे भी जोड़ दिया ।
पालसीम

8

यहां एक स्क्रिप्ट है जो फाइलों को नीचे /path/to/source/rootदिए गए संगत पथ से नीचे ले जाती है /path/to/destination/root

  • यदि कोई स्रोत और गंतव्य दोनों में कोई निर्देशिका मौजूद है, तो सामग्री को पुनरावर्ती रूप से स्थानांतरित कर दिया जाता है।
  • यदि कोई फ़ाइल या निर्देशिका स्रोत में मौजूद है लेकिन गंतव्य में नहीं है, तो उसे स्थानांतरित कर दिया जाता है।
  • गंतव्य में पहले से मौजूद कोई भी फ़ाइल या निर्देशिका पीछे छोड़ दी गई है। (विशेष रूप से विलय निर्देशिकाओं को स्रोत में पीछे छोड़ दिया जाता है। इसे ठीक करना आसान नहीं है।)

खबरदार, अछूता कोड।

export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' \; -o \
                  -exec sh -c 'mv "$0" "$dest/$0"' {} \; -prune \) \
    -o -exec sh -c '
        if ! [ -e "$dest/$0" ]; then
          mv -f "$0" "$dest/$0"
        fi
' {} \;

दो सुधार: आप एक की जरूरत है \;इससे पहले कि -oकी पहली पंक्ति पर findआदेश, और आप बच नहीं करना चाहिए !में if- यह सिर्फ है !, नहीं\!
llhuii

2

यह धागा सालों से वहीं है और अभी भी # 1 रैंक गूगल पर है इसलिए मैं एक और तरीका जोड़ना चाहता था। मैं आम तौर पर यह कैसे करता हूं: उप-टैरिड सामग्री को टारबॉल में पैक करना, टारबॉल को मूल निर्देशिका तक ले जाना और फिर उसे डिफ़ॉल्ट - इनओवराइट व्यवहार के साथ निकालना। यह वही है जो आप देख रहे हैं। बाद में आप अपना उपडर्ड निकाल सकते हैं।

cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz

यह केवल तभी काम करता है जब आपके पास संपीड़ित टार फ़ाइल के लिए अतिरिक्त स्थान हो। और क्या आप वास्तव में निष्कर्षण के बाद अस्थायी टार फाइल को आसपास रखना चाहते हैं?
एंथॉन

Tmp फ़ाइल को निकालने के लिए संपादित कोड। आजकल अंतरिक्ष ज्यादातर मामलों में समस्या नहीं है। #terabyteages
साइमन

0

यदि आपके पास पर्याप्त भंडारण है तो आप इसे निम्न तरीके से कर सकते हैं:

mv -bfv directory_1/* directory_2/ # all duplicate source files/directories 
                                   # will have ~ appended to them
find -name "*~" -delete            # will recursively find and delete all files 
                                   # with ~ on the end

सुनिश्चित करें कि उनमें से ~ के अंत में कोई महत्वपूर्ण फ़ाइल नहीं है, लेकिन अगर आप --suffix=whateveryouwantडिफ़ॉल्ट के बजाय जोड़ सकते हैं ।

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