कुछ फ़ोल्डर्स को छोड़कर, पुनरावर्ती फ़ोल्डर की प्रतिलिपि बनाएँ


197

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


1
मैं कुछ खोजने की कल्पना करता हूं। -नाम * grep / v "बहिष्कृत-पैटर्न" के लिए पाइप जिसे आप नहीं चाहते हैं उसे फ़िल्टर करें और फिर कॉपी करने के लिए cp पर पाइप किया जाए।
I_am_jorf

1
मैं ऐसा कुछ करने की कोशिश कर रहा था, लेकिन एक पाइप के साथ
सीपीपी

1
यह शायद सुपर उपयोगकर्ता के पास जाना चाहिए। जिस कमांड को आप देख रहे हैं वह xargs है। आप कुछ ऐसा भी कर सकते हैं जैसे कि दो तार एक पाइप द्वारा जुड़े हों।
काइल बट

1
हो सकता है कि इसके देर से और यह सही ढंग से सवाल का जवाब नहीं देता है, लेकिन यहां एक टिप है: यदि आप निर्देशिका के केवल तत्काल बच्चों को बाहर करना चाहते हैं, तो आप बैश पैटर्न मिलान का लाभ उठा सकते हैं, जैसेcp -R !(dir1|dir2) path/to/destination
बोरिस डी। तेहरोव

1
ध्यान दें कि !(dir1|dir2)पैटर्न को extglobचालू करने की आवश्यकता है ( shopt -s extglobइसे चालू करने के लिए)।
बोरिस डी। तेहरोव

जवाबों:


334

Rsync का उपयोग करें:

rsync -av --exclude='path1/to/exclude' --exclude='path2/to/exclude' source destination

ध्यान दें कि उपयोग कर रहे हैं sourceऔर source/अलग हैं। एक अनुगामी फ़ोल्डर की सामग्री को कॉपी करने के लिए साधन स्लेश sourceमें destination। ट्रेलिंग स्लैश के बिना, इसका मतलब है कि फ़ोल्डर sourceको कॉपी करें destination

वैकल्पिक रूप से, यदि आपके पास बाहर करने के लिए बहुत सारी निर्देशिकाएँ (या फ़ाइलें) हैं, तो आप उपयोग कर सकते हैं --exclude-from=FILE, जहाँ FILEफ़ाइल या निर्देशिकाओं को बाहर करने वाली फ़ाइल का नाम है।

--exclude इसमें वाइल्डकार्ड भी हो सकते हैं, जैसे कि --exclude=*/.svn*


10
मैं -dry- रन को जोड़ने के लिए सुझाव देता हूं ताकि यह जांचा जा सके कि कौन सी फाइलें कॉपी होने वाली हैं।
लोरेटोपरसी

1
@AmokHuginnsson - आप किन प्रणालियों का उपयोग कर रहे हैं? Rsync को मुख्य धारा के लिनक्स डिस्ट्रोस में डिफ़ॉल्ट रूप से शामिल किया गया है, जिन्हें मैं जानता हूं, जिनमें RHEL, CentOS, डेबियन और उबंटू शामिल हैं, और मेरा मानना ​​है कि यह FreeBSD में भी है।
सिलिकॉनक्रॉस्टर

1
RHEL व्युत्पन्न डिस्ट्रोस के लिए: yum स्थापित rsync, या डेबियन-आधारित रिलीज़ पर: apt-get install rsync। जब तक आप अपने सर्वर को अपने हार्डवेयर पर निरपेक्ष आधार से नहीं बना रहे हैं, यह एक गैर-मुद्दा है। rsync डिफ़ॉल्ट रूप से मेरे Amazon EC2 बक्से पर, साथ ही साथ ZeroLag और RackSpace से मेरे बक्से में स्थापित है।
सिलिकॉनक्रॉस्टर

2
rsync cp की तुलना में बेहद धीमा प्रतीत होता है? कम से कम यह मेरा अनुभव था।
कोजो

2
उदाहरण के लिए git dir को नजरअंदाज करना:rsync -av --exclude='.git/' ../old-repo/ .
nycynik

40

एक पाइप के साथ टार का उपयोग करें।

cd /source_directory
tar cf - --exclude=dir_to_exclude . | (cd /destination && tar xvf - )

तुम भी ssh भर में इस तकनीक का उपयोग कर सकते हैं।


यह दृष्टिकोण अनावश्यक रूप से पहले लक्ष्य स्रोत (और संग्रह में विशेष निर्देशिकाओं को छोड़ देता है) को टार्स करता है और फिर लक्ष्य पर इसे अनटार्स करता है। सिफारिश नहीं की गई!
राउटर डिनर

4
@ आप गलत हैं। यह सबसे अच्छा उपाय है। यह वही करता है जो ओपी ने अनुरोध किया था और यह ओएस की तरह अधिकांश * निक्स की डिफ़ॉल्ट स्थापना पर काम करता है। टैरिंग और अनरेटिंग मक्खी पर बिना किसी फ़ाइल सिस्टम आर्टिफैक्ट (मेमोरी में) के साथ किया जाता है, इस टार + अनटार की लागत नगण्य है।
AmokHuginnsson

@ रूटरडाइंड टार न्यूनतम ओवरहेड है। यह संपीड़न लागू नहीं होता है।
काइल बट

9

आप विकल्प के findसाथ उपयोग कर सकते हैं -prune

इससे एक उदाहरण man find:

       सीडी / स्रोत-डीआईआर
       खोजो। -name .snapshot -prune -o \ (\! -name * ~ -print0 \) |
       cpio -pmd0 / dest-dir

       यह कमांड / source-dir / की सामग्री को / dir-dir को कॉपी करता है, लेकिन छोड़ देता है
       फ़ाइलों और निर्देशिकाओं का नाम .snapshot (और उनमें कुछ भी)। यह भी
       उन फ़ाइलों या निर्देशिकाओं को छोड़ देता है जिनका नाम ~ में समाप्त होता है, लेकिन उनका शंकु नहीं
       तम्बू। निर्माण -rune -o \ (... -print0 \) काफी सामान्य है। 
       यहां विचार यह है कि -प्र्यून से पहले की अभिव्यक्ति उन चीजों से मेल खाती है जो हैं
       छंटनी करना। हालांकि, -प्रत्येक कार्रवाई ही सही है, इसलिए
       निम्नलिखित -o सुनिश्चित करता है कि दाहिने हाथ की ओर का मूल्यांकन केवल के लिए किया जाता है
       वे निर्देशिकाएं जो छंटनी नहीं हुईं (छंटाई की सामग्री
       निर्देशिकाओं का दौरा भी नहीं किया जाता है, इसलिए उनकी सामग्री अप्रासंगिक हैं)।
       -ओ के दाहिने हाथ की अभिव्यक्ति केवल कोष्ठक में है
       विस्तृत जानकारी के लिए। यह जोर देता है कि -print0 कार्रवाई केवल होती है
       उन चीजों के लिए जो -प्र्यून नहीं है उन पर लागू होती है। क्यों कि
       डिफ़ॉल्ट `और 'परीक्षणों के बीच की स्थिति-की तुलना में अधिक कसकर बांधती है
       वैसे भी डिफ़ॉल्ट है, लेकिन कोष्ठक यह दिखाने में मदद करते हैं कि क्या हो रहा है
       पर।

सीधे एक मेनपेज से एक अत्यधिक प्रासंगिक उदाहरण का पता लगाने के लिए सहारा।
डेविड एम

वास्तव में अच्छा लग रहा है! यह ऑनलाइन डॉक्स में भी उपलब्ध है । दुर्भाग्य से cpioअभी तक MSYS2 के लिए पैक नहीं किया गया है।
अंडरस्कोर_ड

3

आप टार --exclude विकल्प के साथ उपयोग कर सकते हैं, और फिर इसे गंतव्य में अनटार कर सकते हैं। जैसे

cd /source_directory
tar cvf test.tar --exclude=dir_to_exclude *
mv test.tar /destination 
cd /destination  
tar xvf test.tar

अधिक जानकारी के लिए टार का आदमी पृष्ठ देखें


2

जेफ के विचार के समान (अप्राप्त):

find . -name * -print0 | grep -v "exclude" | xargs -0 -I {} cp -a {} destination/

क्षमा करें, लेकिन मुझे वास्तव में यह नहीं पता है कि 5 लोगों ने इसे तब उखाड़ फेंका जब यह भर्ती नहीं हुआ था और एक साधारण परीक्षण पर काम नहीं कर रहा था: मैंने इसके लिए एक उप-विभाग में कोशिश की /usr/share/iconsऔर तुरंत मिल गया find: paths must precede expression: 22x22जहां बाद वाला उप-दल में से एक है । मेरी आज्ञा थी find . -name * -print0 | grep -v "scalable" | xargs -0 -I {} cp -a {} /z/test/(वास्तव में /mingw64/share/icons/Adwaita, मैं MSYS2 पर हूँ, इसलिए वास्तव में , लेकिन मैं यह नहीं देख सकता कि यह MSYS2 का दोष कैसे है)
अंडरस्कोर_ड

0
EXCLUDE="foo bar blah jah"                                                                             
DEST=$1

for i in *
do
    for x in $EXCLUDE
    do  
        if [ $x != $i ]; then
            cp -a $i $DEST
        fi  
    done
done

Untested ...


यह गलत है। कुछ समस्याएं: जैसा कि लिखा गया है, यह एक ऐसी फाइल की नकल करेगा, जिसे कई बार बाहर करने की जरूरत नहीं है (इस मामले में बाहर की जाने वाली वस्तुओं की संख्या 4 है)। यहां तक ​​कि अगर आप 'फू' को कॉपी करने का प्रयास करते हैं, तो बहिष्कृत सूची में पहला आइटम, यह तब भी कॉपी किया जाएगा जब आप x = बार पर पहुंच जाएंगे और मैं अभी भी फू हूं। यदि आप पहले से मौजूद उपकरणों (जैसे rsync) के बिना ऐसा करने पर जोर देते हैं, तो प्रतिलिपि को 'x in ...' लूप के बाहर एक स्टेटमेंट में ले जाएँ और 'x के लिए ...' लूप को तार्किक स्टेटमेंट में बदल दें अगर (सच) कॉपी फ़ाइल। यह आपको कई बार कॉपी करने से रोकेगा।
एरिक ब्रोडली

0

@ SteveLazaridis के उत्तर से प्रेरित है, जो विफल होगा, यहां एक POSIX शेल फ़ंक्शन है - बस cpxyout नाम की फ़ाइल में कॉपी और पेस्ट करें $PATHऔर इसे निष्पादन योग्य ( chmod a+x cpr) बनाएं । [स्रोत अब मेरे GitLab में बनाए रखा गया है ।

#!/bin/sh

# usage: cpx [-n|--dry-run] "from_path" "to_path" "newline_separated_exclude_list"
# limitations: only excludes from "from_path", not it's subdirectories

cpx() {
# run in subshell to avoid collisions
  (_CopyWithExclude "$@")
}

_CopyWithExclude() {
  case "$1" in
    -n|--dry-run) { DryRun='echo'; shift; } ;;
  esac

  from="$1"
  to="$2"
  exclude="$3"

  $DryRun mkdir -p "$to"

  if [ -z "$exclude" ]; then
      cp "$from" "$to"
      return
  fi

  ls -A1 "$from" \
    | while IFS= read -r f; do
        unset excluded
        if [ -n "$exclude" ]; then
          for x in $(printf "$exclude"); do
          if [ "$f" = "$x" ]; then
              excluded=1
              break
          fi
          done
        fi
        f="${f#$from/}"
        if [ -z "$excluded" ]; then
          $DryRun cp -R "$f" "$to"
        else
          [ -n "$DryRun" ] && echo "skip '$f'"
        fi
      done
}

# Do not execute if being sourced
[ "${0#*cpx}" != "$0" ] && cpx "$@"

उदाहरण उपयोग

EXCLUDE="
.git
my_secret_stuff
"
cpr "$HOME/my_stuff" "/media/usb" "$EXCLUDE"

यह कहना अनुचित है कि किसी का उत्तर "असफल" होगा, यह बताए बिना कि इसमें क्या गलत है और आप इसे कैसे ठीक करते हैं ...
अंडरस्कोर_ड

@underscore_d: सच है, दृष्टि में, esp के रूप में मैं अब याद नहीं कर सकता कि क्या विफल रहा :-(
go2null

एकाधिक चीजें: (1) यह कई बार फाइलों की नकल करती है और (2) तर्क अभी भी फाइलों को बाहर करने के लिए कॉपी करता है। I = foo का उपयोग करके छोरों के माध्यम से चलाएं: इसे किसी भी अन्य फ़ाइल जैसे i = test.txt के लिए 4 के बजाय 3 बार कॉपी किया जाएगा।
एरिक ब्रोडली

1
स्टीव के जवाब की कमियों को स्पष्ट करने के लिए धन्यवाद @EricBringley। (वह कहते हैं कि यह था अपरीक्षित हालांकि।)
go2null
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.