लिनक्स - केवल नई और बड़ी फ़ाइलों की प्रतिलिपि बनाएँ


2

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

मैं dirA से dirB में उन सभी फ़ाइलों को कैसे कॉपी कर सकता हूं जो dirB में नहीं हैं या यदि dirB में फ़ाइल मौजूद है तो इसे छोटा होने पर अधिलेखित कर दें।

मुझे पता है कि विभिन्न टाइमस्टैम्प या अलग-अलग फ़ाइल आकार के लिए बहुत सारे उदाहरण हैं, लेकिन मैं केवल यह लिखना चाहता हूं कि गंतव्य फ़ाइल छोटी है और किसी भी परिस्थिति में बड़ी नहीं है।

मेरी समस्या की पृष्ठभूमि:
मैंने अपने Minecraft सर्वर पर एक dynmap प्रदान किया है, लेकिन कुछ टाइल गायब हैं या दूषित हैं। फिर मैंने एक और मशीन पर फिर से तेजी से सीपीयू के साथ प्रतिपादन किया और अपने सर्वर पर सभी नई प्रदान की गई फ़ाइलों (~ 50GB / 6.000.000 ~ 4-10 KB PNGs) की नकल की। उसके बाद मैंने देखा कि मेरे नए रेंडर में भी दूषित फाइलें हैं।

बाएं: पुराना रेंडर, राइट: नया रेंडर

पुराना 1 भ्रष्ट नया 1

पुराना २ नए 2 भ्रष्ट

इसके बावजूद मैं सभी फाइलों को अधिलेखित नहीं करना चाहता हूं, लेकिन केवल वे ही हैं जो बड़े हैं (भ्रष्ट कम डेटा ले जाते हैं और छोटे होते हैं)।


आदेशों के cpसंयोजन के साथ उपयोग करें cmpया बेहतर उपयोग करें rsyncजिसमें आपके पास सभी विकल्प हैं
एलेक्स

मुझे rsync के साथ क्या विकल्प चुनना है? मुझे बड़ी फ़ाइलों के लिए कुछ भी नया या अलग आकार नहीं मिला। इसीलिए मैंने पूछा।
दास किक्स

statफ़ाइलों का आकार प्राप्त करने के लिए दोनों स्थानों पर फ़ाइलों का उपयोग करें और फिर कॉपी करें यदि यह आपकी शर्तों को पूरा करता है
एलेक्स 13

खैर, यह एक चुनौती, के लिए देखा rsyncविकल्प की जरूरत है, लेकिन सही एक खोजने के लिए असफल है, तो एक आसान तरीका के साथ चला गया
एलेक्स

जवाबों:


2

एक गंदा तरीका हो सकता है, लेकिन मुझे आशा है कि यह वही है जो आप ढूंढ रहे हैं

#!/bin/bash

### Purpose:
# Copy huge amount of files from source to destination directory only if
# destination file is smaller in size than in source directory
###

src='./d1' # Source directory
dst='./d2' # Destination directory

icp() {
  f="${1}";
  [ -d "$f" ] && {
    [ ! -d "${dst}${f#$src}" ] && mkdir -p "${dst}${f#$src}";
    return
  }

  [ ! -f "${dst}/${f#$src/}" ] && { cp -a "${f}" "${dst}/${f#$src/}"; return; }
  fsizeSrc=$( stat -c %s "$f" )
  fsizeDst=$( stat -c %s "${dst}/${f#$src/}" )
  [ ${fsizeDst} -lt ${fsizeSrc} ] && cp -a "${f}" "${dst}/${f#$src/}"
}

export -f icp
export src
export dst

find ${src} -exec bash -c 'icp "$0"' {} \;

धन्यवाद। मैंने कुछ परीक्षण डेटा के साथ इसका परीक्षण किया और यह आवश्यकतानुसार काम करता है। : लेकिन मैं क्योंकि निर्देशिका बहुत सारी फ़ाइलें (लगभग 6.000.000) शामिल हैं एक समस्या है जब मैं अपने वास्तविक डेटा पर अमल करने के लिए चाहते हैं ls argument list too long)
दास Keks

यह ऑपरेशन सिस्टम लिमिट है (आप इसे अपने सिस्टम के लिए प्राप्त कर सकते हैं:) getconf ARG_MAX। आपके पास संभवतः बहुत लंबी फ़ाइल नाम या बहुत गहरी निर्देशिका संरचना है, इसलिए ऐसे नामों के साथ findफ़ीड lsकरते समय यह कमांड लाइन के लिए अधिकतम अनुमत लंबाई से अधिक है। मैंने lsकमांड को खत्म करने के लिए थोड़ी स्क्रिप्ट को संशोधित किया , क्या आप इस नए संस्करण को आज़मा सकते हैं।
एलेक्स

यदि स्क्रिप्ट फिर से चोक हो जाएगी, तो आप कुछ छोटे पथ पर बढ़ते हुए पूर्ण पथ को कम करने का प्रयास कर सकते हैं। उदाहरण के लिए sudo mkdir -m 777 /aतो स्रोत निर्देशिका माउंट /aके रूप में sudo mount --bind /pretty/long/prefix/to/source/directory /aतो का उपयोग /aमेरी स्क्रिप्ट में। जब आपने किया, /aइश्यू कमांड द्वारा अनमाउंट करें :sudo umount /a
एलेक्स

मुझे लगता है कि यह पथ की लंबाई नहीं है क्योंकि सबसे लंबा पथ (फ़ाइल नाम सहित) लगभग 80 वर्ण लंबा है। क्या यह सूची हो सकती है, जो प्रत्येक के लिए पारित की गई है, जो बहुत लंबी है? मुझे लगता है कि यह सवाल कुछ इसी तरह से लक्षित करता है: unix.stackexchange.com/questions/128559/…
das Keks

हो सकता diff --brief -r dir1/ dir2/है कि यह एक अच्छा तरीका हो और फिर आउटपुट की प्रत्येक पंक्ति के लिए कुछ करें। मैं शाम को कुछ इस तरह का निर्माण करने की कोशिश करूँगा।
दास किक्स

1

आप rsync कमांड का उपयोग कर सकते हैं

वाक्य - विन्यास :

-a = archive mode
-v = increase verbosity
-z = compress file data during the transfer
--progress = show progress during transfer

rsync -avz --progress <source path> <destination path>

आप --deleteगंतव्य निर्देशिका से बाहरी फ़ाइलों को हटाने के लिए उपयोग कर सकते हैं

rsync -avz --delete --progress <source path> <destination path>

तो आपकी आज्ञा होगी:

rsync -avz --delete --progress dirA dirB

1
क्या -a ध्वज उन सभी फ़ाइलों की प्रतिलिपि नहीं बनाता है जिनमें नए टाइमस्टैम्प या अलग फ़ाइल आकार हैं? यह महत्वपूर्ण है कि केवल छोटी फ़ाइलों को ओवरराइट किया जाएगा।
दास किक्स

यह आदेश कुछ भी अधिलेखित नहीं करेगा, यह केवल बदली हुई फ़ाइल और नई फ़ाइल की प्रतिलिपि बनाएगा जो गंतव्य निदेशक के अंतर्गत उपलब्ध नहीं है।
पंकज जैक्सन

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

0

मेरी समस्या भी ऐसी ही थी। मैं दूरस्थ फ़ोल्डर से फ़ाइलों को स्थानीय एक में सिंक्रनाइज़ करना चाहता था, लेकिन केवल उन दूरस्थ फ़ाइलों की प्रतिलिपि बनाता हूं जो स्थानीय फ़ाइलों के अनुसार बड़ी थीं।

Rsync के साथ मेरा वर्कअराउंड ऐसा था, जो वास्तव में बैश वन-लाइनर था:

for x in $(ls -1 home/me/local/folder/*)
do
    eachsize=$(stat -c "%s")
    rsync -avz --progress --max-size=${eachsize} remote:/home/you/folder/${x} .
done

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


lsउस तरह का उपयोग न करें ; बस करो for x in home/me/local/folder/*
जी-मैन

तुम सही हो; हालांकि मेरी बात बनाने के लिए।
user32916

0

मैंने इसे कुछ इस तरह से संशोधित किया है:

# Copy src to destination if the src is larger.
function copy_if_larger() {
  local src="$1"
  local dest="$2"

  [ ! -f "$1" ] return
  [ ! -f "$2" ] return

  local srcSize=$( stat -c %s "$1")
  local dstSize=$( stat -c %s "$2")

  [ ${dstSize} -lt ${srcSize} ] && {
    cp -a "$1" "$2"
  }
  return
}

फिर मैंने उन फ़ाइलों को समायोजित करने के लिए एक और विधि लिखी, जिन्हें मैं कॉपी करके उन्हें copy_if_larger फ़ंक्शन में फीड करना चाहता हूं।

function do_copy_if_larger() {
  # trim prefix
  local suffix=$(echo "$1" | cut -c 10-)
  copy_if_larger "$1" "/dest/path/$suffix"
}

# make the functions visible to the subshell.
export -f copy_if_larger
export -f do_copy_if_larger

# copy all larger jpeg files over /dest/path
find . -name '*jpg' | xargs -n 1 bash -c 'do_copy_if_larger "$@"' {}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.