2008-08-26 15 views
34

सपाट प्रतिलिपि यूनिक्स बैश खोल (विशेष रूप से मैक ओएस एक्स तेंदुआ) क्या एक ही गंतव्य फ़ोल्डर में (उपनिर्देशिकाएं) एक फ़ोल्डर पदानुक्रम से किसी विशेष एक्सटेंशन के होने हर फ़ाइल की प्रतिलिपि करने का सबसे सरल तरीका होगा पर (subfolders के बिना)?यूनिक्स शेल फ़ाइल फ़ोल्डर संरचना

जाहिर है स्रोत पदानुक्रम में डुप्लिकेट प्रविष्टियां रखने की समस्या है। अगर वे ओवरराइट हो जाते हैं तो मुझे कोई फर्क नहीं पड़ता।

उदाहरण:

/dest/a.txt 
/dest/b.txt 

उत्तर

51

बैश में:

find /foo -iname '*.txt' -exec cp \{\} /dest/ \; 
मैं एक फ़ोल्डर नाम 'गंतव्य' करने के लिए निम्न पदानुक्रम

/foo/a.txt 
/foo/x.jpg 
/foo/bar/a.txt 
/foo/bar/c.jpg 
/foo/bar/b.txt 

में हर .txt फ़ाइल को कॉपी करें और प्राप्त करने की आवश्यकता

find पथ /foo wildca मिलान के तहत सभी फाइलों को मिलेगा rd *.txt, मामला असंवेदनशील (यही -iname का मतलब है)। प्रत्येक फ़ाइल के लिए, findcp {} /dest/ निष्पादित करेंगे, {} के स्थान पर पाया फ़ाइल के साथ।

+3

-exec cp -t dest/{} + तेज होगा, क्योंकि इसे कई तर्कों के साथ केवल एक बार सीपी चलाने की ज़रूरत है। - लक्ष्य-निर्देशिका के लिए छोटा है। -l हार्डलिंक्स बनाने के लिए यहां उपयोगी हो सकता है। बजाय। और शायद -u, प्रत्येक फ़ाइल नाम के लिए नवीनतम संस्करण के साथ समाप्त करने के लिए, पहले एक खोज के बजाय आता है। –

+0

यहां सामान्य बैश प्रश्न ... {} विशिष्ट है या यह पाइप किए गए मूल्य का प्रतिनिधित्व करने का एक तरीका है? –

+0

@BrianBolton '{}' 'ढूंढने के लिए विशिष्ट है –

13

मैग्नस समाधान के साथ एकमात्र समस्या यह है कि यह प्रत्येक फ़ाइल के लिए एक नई "सीपी" प्रक्रिया को बंद कर देता है, जो बहुत प्रभावी नहीं है, खासकर यदि बड़ी संख्या में फाइलें हैं।

लिनक्स (या GNU coreutils साथ अन्य प्रणालियों) पर आप कर सकते हैं:

find . -name "*.xml" -print0 | xargs -0 echo cp -t a 

(। -0 यह काम करने के लिए अनुमति देता है आपके फ़ाइलनामों अजीब वर्ण हो जब - रिक्त स्थान की तरह - उन में)

दुर्भाग्य से मैं Macs बीएसडी शैली उपकरणों के साथ आने लगता है। किसी को "-t" स्विच के बराबर "मानक" पता है?

+0

इसके साथ एकमात्र समस्या यह है कि आप कमांड लाइन से अधिक हो सकते हैं फाइलों की संख्या बहुत बड़ी है तो xargs का उपयोग कर बफर। –

+0

सच नहीं है। ओएस एक्स मैन पेज से (लेकिन प्रत्येक यूनिक्स पर मैंने सही उपयोग किया है): "कमांड लाइन पर निर्दिष्ट किसी भी तर्क को प्रत्येक आमंत्रण पर उपयोगिता के लिए दिया जाता है, उसके बाद xargs के मानक इनपुट से पढ़े गए तर्कों के _ome संख्या_ के बाद। मानक इनपुट समाप्त होने तक उपयोगिता _repeatedly execed_ है। " (जोर मेरा।) –

+0

मेरा मानना ​​है कि मैंने कुछ समय पहले साइगविन पर व्यवहार देखा था, जहां उसने ऐसा नहीं किया था। मैंने फिर निष्कर्ष निकाला कि पॉज़िक्स व्यवहार था (वास्तव में दस्तावेज़ की जांच करने के लिए मेरी गलती)। –

1

जहां तक ​​एक फ्रीबीएसडी बॉक्स पर सीपी के लिए मैन पेज जाता है, वहां स्विच के लिए कोई आवश्यकता नहीं होती है। दो से अधिक नाम पारित होने पर सीपी कमांड लाइन पर अंतिम तर्क मानने के लिए अंतिम निर्देशिका मान लेगा।

+0

का मुद्दा यह है कि यह आपको लक्ष्य को पहले तर्कों में से एक के रूप में रखने देता है। xargs मध्य में तर्क डालना आसान नहीं बनाता है। –

3

तुम सच में सिर्फ एक आदेश चलाना चाहते हैं, क्यों नहीं विपक्ष एक और इसे चलाने के? इसलिए जैसा:

$ find /foo -name '*.txt' | xargs echo | sed -e 's/^/cp /' -e 's|$| /dest|' | bash -sx 

लेकिन उस बात के बहुत ज्यादा प्रदर्शन के लिहाज से जब तक आप इस बहुत कुछ कर या फ़ाइलों की एक टन की जरूरत नहीं होगी। हालांकि, नाम टक्कर से सावधान रहें। मुझे लगता है कि जीएनयू सीपी कम से कम टकराव की चेतावनी के परीक्षण में देखा:

cp: will not overwrite just-created `/dest/tubguide.tex' with `./texmf/tex/plain/tugboat/tubguide.tex' 

मुझे लगता है कि साफ है:

$ find /foo -name '*.txt' | xargs -i cp {} /dest 

कम वाक्य रचना -exec विकल्प की तुलना में याद करने के लिए।

10

ऊपर दिए गए उत्तरों नाम टकराव की अनुमति नहीं देते क्योंकि पूछताछकर्ता फ़ाइलों को अधिक लिखित नहीं मानते थे।

मुझे लगता है कि फाइलें अधिक लिखित हैं इसलिए एक अलग दृष्टिकोण के साथ आया। पथ में प्रत्येक/को प्रतिस्थापित करना - नामों में पदानुक्रम रखें, और सभी फ़ाइलों को एक फ्लैट फ़ोल्डर में रखता है।

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

find ./from -type f | awk '{ str=$0; sub(/\.\//, "", str); gsub(/\//, "-", str); print "mv " $0 " ./to/" str }' | bash 

जहां ./from और ./to एमवी से निर्देशिका में हैं।

+2

यह रिक्त स्थान जैसे फ़ाइल नामों में अजीब वर्णों के लिए खाता नहीं है। –

+3

@ NathanJ.Brauer आप इसे अंत में एमवी कमांड में \ "के न्यायसंगत रखने के साथ ठीक कर सकते हैं। (मैंने इसे दिखाने के लिए जवाब संपादित करने का प्रयास किया लेकिन अस्वीकार कर दिया। धन्यवाद मॉडरेटर।) – Paul