प्रतिलिपि (cp) कमांड कार्रवाई को पूर्ववत करें


14

मैंने टर्मिनल में bellow कमांड लाइन का उपयोग करके स्रोत फ़ोल्डर से गंतव्य फ़ोल्डर में कुछ फ़ाइल की प्रतिलिपि बनाई।

sudo cp From_SOURCE/* To_DESTINATION/

अब मैं इस आदेश को पूर्ववत करना चाहता हूं।


मुझे यकीन नहीं है कि मैं समझता हूं। बस कॉपी निकाल दूं? (sudo rm फ़ाइल)
याकूब Vlijm

@JacobVlijm यह एक अलग कमांड नहीं है। अगर मैं कॉपी नहीं करता, तो मैं आपके सुझाए गए आदेश का उपयोग पहले कर सकता था। और मुझे अधिक से अधिक समय इस कमांड का उपयोग करके कॉपी की गई 1000 से अधिक फाइलों को हटाना है?
α atsнιη

@ कासिया - एक विकल्प उन सभी फ़ाइलनामों को ढूंढना होगा जिन्हें चुना गया था From_SOURCE/*, और उन लोगों को हटा दिया गया था To_DESTINATION/; इसे बैश के साथ किया जा सकता है - यहाँ की समस्याओं में cp कमांड को कुछ भी शामिल किया जा सकता है, सहानुभूति की प्रतिलिपि बनाई गई थी, नामों में रिक्त स्थान वाली फाइलें, आदि - इसलिए यह समस्या हो सकती है और थोड़ा निराला हो सकता है। एक आदर्श 'पूर्ववत' विकल्प में बहुत सारे सामानों के लिए खाता होगा।
विल्फ

जवाबों:


13

अगर मैं अच्छी तरह से समझता हूं, तो निम्नलिखित मामला है:

  • आपने मौजूदा निर्देशिका में फ़ाइलों की (संभवतः बड़ी) संख्या की प्रतिलिपि बनाई है, और आपको कार्रवाई को उलटने की आवश्यकता है / चाहिए।
  • लक्षित निर्देशिका में कई अन्य फाइलें हैं, जिन्हें आपको वहां रखने की आवश्यकता है, जिससे निर्देशिका से सभी फ़ाइलों को केवल निकालना असंभव है

नीचे दी गई स्क्रिप्ट मूल (स्रोत) निर्देशिका में दिखती है और उन फ़ाइलों को सूचीबद्ध करती है। फिर यह उस निर्देशिका में दिखता है जिसे आपने फ़ाइलों को कॉपी किया है, और केवल सूचीबद्ध फ़ाइलों को हटा दिया है, क्योंकि वे स्रोत निर्देशिका में मौजूद हैं।

tryतत्व उदाहरण मामले में आप कुछ फ़ाइलों को मैन्युअल रूप से पहले से ही हटा दिया हो सकता है, या यदि स्रोत निर्देशिका से नहीं सभी फाइलों को गंतव्य के लिए प्रतिलिपि की गई के लिए, त्रुटियों को रोकने के लिए जोड़ा गया है। यदि आपको sudo विशेषाधिकार की आवश्यकता है, तो बस स्क्रिप्ट को "sudo" (नीचे देखें) के साथ चलाएं।

लिपी

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for root, dirs, files in os.walk(source_dir):
    for name in files:
        try:
            os.remove(target_folder+"/"+name)
        except FileNotFoundError:
            pass

कैसे इस्तेमाल करे

  • एक खाली फ़ाइल में स्क्रिप्ट पेस्ट करें, इसे सहेजें reverse.py,
  • स्रोत और लक्ष्य फ़ोल्डर के लिए सही पथ सम्मिलित करें,
  • सुविधा कारणों से इसे निष्पादन योग्य बनाएं,
  • इसे कमांड द्वारा चलाएं:

    [sudo] /path/to/reverse.py
    

चेतावनी

पहले एक परीक्षण निर्देशिका पर प्रयास करें अगर मैं अच्छी तरह से समझ गया कि आपको क्या हासिल करने की आवश्यकता है!


यदि sourcedirectory "सपाट" है

यदि स्रोत निर्देशिका में कोई उप-निर्देशिका नहीं है, तो स्क्रिप्ट और भी सरल हो सकती है:

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for file in os.listdir(source_dir):
    try:
        os.remove(target_folder+"/"+file)
    except FileNotFoundError:
        pass

ध्यान दें

यदि प्रतिलिपि कार्रवाई गंतव्य में एक समान नाम वाली फ़ाइल को ओवररिप्ट (प्रतिस्थापित) करती है, तो फ़ाइल को हटा दिया जाएगा, लेकिन मूल फ़ाइल (निश्चित रूप से) स्क्रिप्ट द्वारा वापस नहीं लाई जाएगी। धारणा यह है कि कोई नाम क्लैश नहीं हैं।


यह काम करता है, धन्यवाद। मैं इसे चला रहा हूं sudo python3 reverse.py। मैं आपका उत्तर स्वीकार करता हूं।
α atsнιη

उत्तम! एक अच्छे सवाल के लिए धन्यवाद, जो एक ऐसी स्थिति का वर्णन करता है जो शायद हम सभी में है :)
याकूब Vlijm

नोट: यदि स्रोत की कोई भी फ़ाइल गंतव्य में किसी फ़ाइल को ओवरराइड करती है क्योंकि उसका नाम समान था, तो आप बस इसे अन-डू नहीं कर सकते, और यह स्क्रिप्ट बस इसे हटा देगी। यहाँ धारणा यह है कि जब आपने प्रारंभिक कार्य किया था तब कोई नाम का टकराव नहीं था cp
thomasrutter

@neon_overload सही, मेरे उत्तर में इसे संपादित किया।
जैकब व्लिजम

यह काम नहीं करता है cp -r। मैं बदल os.removeगया print, और यह मौजूद नहीं है कि फ़ाइलों का एक गुच्छा outputting है। मुझे लगता है कि यह उपनिर्देशिका याद कर रहा है, और अंत में केवल फाइलों को सूचीबद्ध कर रहा है।
टाइपरवार

7

टी एल; डॉ:

सभी फाइलें जो दोनों में मौजूद हैं srcऔर destउन्हें destइस तरह से हटाया जा सकता है :

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;

चरण-दर-चरण, स्पष्टीकरण के लिए, नीचे देखें।

समस्या को सरल बनाना:

यह समझने के लिए कि हम वास्तव में क्या करना चाहते हैं, हम इसे लागू करके शुरू करते हैं:

जिस कमांड को हम पूर्ववत करना चाहते हैं वह है

sudo cp From_SOURCE/* To_DESTINATION/

पूर्ववत् कैसे करें, sudoयह समझने के लिए प्रासंगिक नहीं है।

मैं निर्देशिका नाम का उपयोग करेंगे srcके लिए From_SOURCEऔर destके लिए To_DESTINATION

अब, हमारा आदेश है:

cp src/* dest/

यदि srcफ़ाइलें हैं f1, f2और f3, और निर्देशिका d1और d2, खोल करने के लिए है कि आदेश का विस्तार:

cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/

जैसे विकल्पों के बिना -r, -Rया -a, कमांड cpनिर्देशिकाओं की नकल नहीं करता है।
इसका मतलब है, उनमें से प्रत्येक के लिए एक त्रुटि दिखाते हुए, कमांड उन्हें छोड़ देगी:

$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'

इसका मतलब है, हमने केवल साधारण फ़ाइलों की प्रतिलिपि बनाई है, और कोई निर्देशिका नहीं, के लिए dest

तय करना है कि किन फाइलों को निकालना है:

संभवतः फाइलों में destभी इसी नाम की फाइलें थीं src। इस मामले में, फाइलें अधिलेखित कर दी गईं (1)। उनके लिए बहुत देर हो चुकी है, क्षमा करें। उन्हें नवीनतम बैकअप से वापस लाएं।

जो फाइलें हैं, उनके बारे में हम केवल उन्हीं फाइलों को हटाना चाहते हैं जिनकी नकल की गई है। ये फ़ाइलें दोनों निर्देशिकाओं में समान नाम और समान सामग्री के साथ मौजूद हैं।

इसलिए हम इन फाइलों की तलाश करते हैं:

सबसे पहले, हम cdमें src, क्योंकि यह निम्न findआदेशों को बहुत सरल बनाता है, और भाग्य के पूर्ण पथ के लिए एक चर सेट करता है:

$ cd src
$ destdir="$(readlink -f dest)"

फिर, हम src में सभी फाइलों को सूचीबद्ध करते हैं:

$ find . -maxdepth 1 -type f

और, मिली प्रत्येक फ़ाइल के लिए, cmpयह जांचने के लिए उपयोग करें कि क्या भाग्य में समान सामग्री वाली कोई फ़ाइल है:

$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print

फ़ाइलों को हटा रहा है, ध्यान से:

ये फाइलें वे हैं जिन्हें हम हटाना चाहते हैं। लेकिन यह सुनिश्चित करने के लिए, हम उन्हें पहले एक अलग निर्देशिका में ले जाते हैं - और उन्हें चलाने से पहले कमांड पर एक नज़र डालते हैं:

$ toDelete=/tmp/toDelete ; mkdir -p "$toDelete"
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec echo mv -n "$destdir/{}" "$toDelete"/ \;
mv -n /path/to/dest/./f1 /tmp/toDelete/`
mv -n /path/to/dest/./f2 /tmp/toDelete/`
mv -n /path/to/dest/./f3 /tmp/toDelete/`

अछा लगता है! अब हम echoअसली mvकमांड्स को चलाने के लिए छोड़ सकते हैं :

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;

से सभी फाइलें destकि से नकल कर रहे थे srcवास्तव में में एक ही है, और अभी भी srcऔर dest, में अब कर रहे हैं /tmp/toDelete/, और एक आखिरी बार देख लेने के बाद हटाया जा सकता है।


नोट:
(1) जाँच करें कि क्या cpकोई अन्य व्यक्ति cp -iऐसा है या नहीं, जो पहले पूछकर ओवरराइटिंग फ़ाइलों को रोक सकता है।


5

यह पुराना है, लेकिन मैं सिर्फ एक शुद्ध बैश उत्तर पोस्ट करना चाहता था:

पहले निर्देशिका में परिवर्तन करें जहाँ आपने फ़ाइलों की प्रतिलिपि बनाई है।

cd dest

फिर, lsस्रोत निर्देशिका और आउटपुट को पाइप मेंrm

ls source | xargs rm


2
पार्सिंग lsआमतौर पर एक बुरा विचार है। mywiki.wooledge.org/ParsingLs मैं आपके पोस्ट को डाउन नहीं करूंगा, लेकिन इसे नोट करना होगा।
सेर्गेई कोलोडियाज़नी

@SergiyKolodyazhnyy अच्छा बिंदु। कभी भी कम न करें: rm `ls`- पहले से खाली फोल्डर और जब फाइल में बिना स्पेस और न्यूलाइन्स के नाम हों।
मल्टीफिक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.