बैश: कॉपी नाम फ़ाइलों की पुनरावृत्ति, फ़ोल्डर संरचना को संरक्षित करना


103

मैं उम्मीद कर रहा था:

cp -R src/prog.js images/icon.jpg /tmp/package

गंतव्य डायर में एक सममित संरचना उत्पन्न करेगा:

/tmp
|
+-- package
    |
    +-- src
    |   |
    |   +-- prog.js
    |
    +-- images
        |
        +-- icon.jpg

लेकिन इसके बजाय, दोनों फ़ाइलों को / tmp / package में कॉपी किया जाता है। एक सपाट प्रति। (यह OSX पर है)।

क्या एक साधारण बैश फ़ंक्शन है जिसका उपयोग मैं सभी फाइलों को कॉपी करने के लिए कर सकता हूं, जिसमें गंतव्य निर्देशिका के भीतर वाइल्डकार्ड (जैसे src / *। Js) द्वारा निर्दिष्ट फाइलों को उनके सही स्थान पर शामिल करना शामिल है। थोड़ा सा "प्रत्येक फ़ाइल के लिए, चलाएं mkdir -p $(dirname "$file"); cp "$file" $(dirname "$file")", लेकिन शायद एक ही आदेश।

यह एक प्रासंगिक धागा है, जो बताता है कि यह संभव नहीं है। लेखक का समाधान हालांकि मेरे लिए इतना उपयोगी नहीं है, क्योंकि मैं केवल फाइलों की सूची, वाइल्डकार्ड या नहीं प्रदान करना चाहूंगा, और उन सभी को गंतव्य डायर को कॉपी किया है। IIRC MS-DOS xcopy ऐसा करता है, लेकिन लगता है कि cp के लिए कोई समकक्ष नहीं है।

जवाबों:


153

क्या आपने --parents विकल्प का उपयोग करने की कोशिश की है? मुझे नहीं पता कि ओएस एक्स का समर्थन करता है, लेकिन यह लिनक्स पर काम करता है।

cp --parents src/prog.js images/icon.jpg /tmp/package

यदि वह OS X पर काम नहीं करता है, तो प्रयास करें

rsync -R src/prog.js images/icon.jpg /tmp/package

ऐफ ने सुझाव दिया।


4
धन्यवाद। मैक पर "cp --parents" संभव नहीं है, लेकिन अन्य यूनिक्स के लिए झंडा जानना अच्छा है। rsync -R इस समस्या का सबसे सरल पोर्टेबल समाधान है।
Mahemoff

1
मैंने इसे इसकी भव्यता / यादगार के लिए स्वीकार कर लिया, लेकिन अभी पता चला है कि यह पूरी निर्देशिका (OSX पर कम से कम) की प्रतिलिपि नहीं करता है, जबकि नीचे वाला टार करता है।
mahemoff

cp --parentsOSX (BSD cp) में अवैध विकल्प है, लेकिन gcp(GNU cp) ठीक काम करता है। यदि यह अभी तक आपके सिस्टम में नहीं है brew install coreutils। यू में जी-प्रीफिक्स के साथ कई बर्तन होंगे।
किब

@ अल्हेमॉफ़ cp -R --parentsऔर rsync -rRफ़ाइलों और निर्देशिकाओं दोनों को अपेक्षाकृत रूप से कॉपी करता है।
वोर्टिको

22

एक रास्ता:

tar cf - <files> | (cd /dest; tar xf -)

ओह, मुझे अपने उत्तर से यह बहुत अच्छा लगता है।
EMPraptor

4
आप के -Cलिए chdir करने के लिए विकल्प का उपयोग भी कर सकते हैं - tar cf - _files_ | tar -C /dest xf -या ऐसा कुछ।
D.Shawley

धन्यवाद, यह संक्षिप्त है, हालांकि मैं सादगी के लिए rsync पसंद करता हूं।
ममेफॉफ

1
महान! क्या कोई जानता है कि इसे शेल कमांड में कैसे बदलना है? इसे एन इनपुट को स्वीकार करना चाहिए, पहला एन -1 कॉपी करने के लिए फाइलें हैं, और अंतिम गंतव्य फ़ोल्डर है।
अरोड करें

@arod $ {! #} अंतिम परम है और पूर्ववर्ती तर्क stackoverflow.com/questions/1215538/… प्राप्त करने के लिए इसका उपयोग करें । यदि आप कमांड लिखते हैं, तो कृपया यहाँ दिए गए लिंक से लिंक करें।
ममेफॉफ

18

वैकल्पिक रूप से, यदि आप पुराने स्कूल में हैं, तो cpio का उपयोग करें:

cd /source;
find . -print | cpio -pvdmB /target

स्पष्ट रूप से, आप फ़ाइल सूची को अपने दिल की सामग्री को फ़िल्टर कर सकते हैं।

'-P' विकल्प 'पास-थ्रू' मोड (इनपुट के लिए '-i' या आउटपुट के लिए '-ओ') के लिए है। '-V' क्रिया है (फाइलों को सूचीबद्ध करें क्योंकि वे संसाधित हैं)। '-M' संशोधन बार संरक्षित करता है। '-B' का अर्थ है 'बड़े ब्लॉक' (जहां बड़े ब्लॉक 512 बाइट्स के बजाय 5120 बाइट्स हैं) का उपयोग करें; यह संभव है कि इन दिनों इसका कोई प्रभाव न हो।


1
विकल्प -print0के संयोजन के साथ उपयोग करना बेहतर है --nullताकि यह विशेष वर्णों के साथ टूट न जाए और जैसे:find . -print0 | cpio -pvdmB --null /target
haridsv

इसे पुराने-स्कूल कहें, इसे पोर्टेबल कहें, इसे जो भी कहें, लेकिन मैं cpioइस कार्य के लिए निश्चित रूप से विश्वास करता हूं । मैं इस बात से सहमत हूं कि -print0और -nullविकल्पों का उपयोग किया जाना चाहिए, अन्यथा, किसी बिंदु पर, कोई व्यक्ति आपको कुछ फ़ोल्डर देगा जिसमें 'विशेष वर्ण' (रिक्त स्थान, सबसे अधिक संभावना) और कुछ होगा। ऐसा नहीं है कि मैं व्यक्तिगत अनुभव से बोल रहा हूं, लेकिन आप फाइलों के एक समूह का बैकअप लेने की कोशिश कर सकते हैं और केवल उनमें से आधे के साथ अंत हो सकता है क्योंकि रिक्त स्थान फिल्नाम में होने के कारण वापस आ गए हैं। (ठीक है, मैं व्यक्तिगत अनुभव से बोल रहा हूँ।)
बबलडेलवे ०२५

@ bballdave025: आप केवल उन समस्याओं के साथ चलते हैं, cpioजैसे कि अगर फ़ाइलनामों में नया नाम होता है - तो आप सामान्य रूप से दो (या अधिक) फ़ाइलनामों के बारे में एक त्रुटि संदेश के साथ समाप्त करते हैं, जो फ़ाइल नाम में प्रत्येक नई पंक्ति के लिए नहीं मिला है। (कभी-कभी, आपको संदेश कम मिल सकते हैं - लेकिन परीक्षण मामले के निर्माण में काफी सावधानी की आवश्यकता होती है।) जब मैंने उपयोग किया cpio, तो कोई --nullविकल्प नहीं था ; डबल-डैश विकल्प SVR4 विकल्प नोटेशन का हिस्सा नहीं थे, और अवधारणा भी -print0मौजूद नहीं थी find। लेकिन यह एक लंबे समय से पहले (उदाहरण के लिए 90 के दशक के मध्य में है। लिनक्स से पहले प्रभुत्व हासिल किया था)।
जोनाथन लेफ़लर 16

विवरण के लिए धन्यवाद, @Jonathan_Leffler। मुझे यहां सीखने का सामान पसंद है। अब, मैं यह याद रखने की कोशिश कर रहा हूं कि मैंने कौन-सी पुनरावृत्ति-कॉपी की गलती की, जिसने मुझे रिक्त स्थान के साथ समस्याएं दीं - बहुत सारे तरीके हैं जो मैं उस गलती को कर सकता था,
bballdave025

@ bballdave025- एक संभावना xargsमिश्रण में उपयोग कर रहा है - यह सफेद स्थान पर विभाजित होता है - रिक्त स्थान, टैब, नईलाइन्स। OTOH, मुझे यकीन नहीं है कि आप कैसे या क्यों करेंगे। cpioआउटपुट मोड पर GNU manul प्रति लाइन एक फ़ाइल नाम के बारे में स्पष्ट है। SVR4 उपयोगकर्ता पुस्तिका (मुद्रित 1990) अस्पष्ट है: cpio -o(कॉपी-आउट मोड) पैथनामों की सूची प्राप्त करने के लिए मानक इनपुट को पढ़ता है और उन फाइलों को मानक आउटपुट पर पथनाम और स्थिति जानकारी के साथ कॉपी करता है। इसलिए, यह एक मौका है, कि इसने रिक्त स्थान पर नामों को तोड़ दिया है।
जोनाथन लेफलर

16

rsync का -R विकल्प वही करेगा जो आप अपेक्षा करते हैं। यह एक बहुत ही सुविधा संपन्न फाइल कॉपियर है। उदाहरण के लिए:

$ rsync -Rv src/prog.js images/icon.jpg /tmp/package/
images/
images/icon.jpg
src/
src/prog.js

sent 197 bytes  received 76 bytes  546.00 bytes/sec
total size is 0  speedup is 0.00

नमूना परिणाम:

$ find /tmp/package
/tmp/package
/tmp/package/images
/tmp/package/images/icon.jpg
/tmp/package/src
/tmp/package/src/prog.js


1

प्रयत्न...

for f in src/*.js; do cp $f /tmp/package/$f; done

तो आप मूल रूप से क्या कर रहे थे ...

for f in `echo "src/prog.js images/icon.jpg"`; do cp $f /tmp/package/$f; done

या

v="src/prog.js images/icon.jpg"; for f in $v; do cp $f /tmp/package/$f; done

आप की जरूरत नहीं है echoया $vयहाँ। यदि गंतव्य में संबंधित निर्देशिका मौजूद नहीं है, तो भी यह विधि विफल हो जाएगी।
वीजुन झोउ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.