चर विस्तार के साथ बैश स्क्रिप्ट में -exec खोजें


14

मैं बैश स्क्रिप्ट में नीचे के समान कमांड चलाने की कोशिश कर रहा हूं। इसे सभी सबफ़ोल्डर्स के माध्यम से खोजना चाहिए $sourcedirऔर एक निश्चित प्रकार की सभी फ़ाइलों को रूट स्तर तक कॉपी करना चाहिए $targetdir

#!/bin/bash

# These are set as arguments to the script, not hard-coded
sourcedir="/path/to/sourcedir"
targetdir="/path/to/targetdir"

find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2/`basename "$1"`"' "{}" "$targetdir" \;

यह बहुत करीब लगता है, सिवाय इसके कि इसमें पास {}नहीं किया जा रहा $2है-exec sh -c ...

मैं इसे संभव के रूप में "सही तरीके" के करीब करना चाहूंगा, फिल्नाम में विशेष पात्रों के लिए सहिष्णुता (विशेष रूप से एकल उद्धरण) के साथ।

संपादित करें: मैं देख रहा हूं कि लोग चाइनिंग का उपयोग करने xargsया तर्क देने का सुझाव दे रहे हैं । मैं इस धारणा के तहत था कि यह सीमित तर्कों के लिए ही ठीक है। यदि मेरे पास है, उदाहरण के लिए, हजारों .jpg फाइलें मैं कई गैलरी निर्देशिकाओं से एक विशाल स्लाइड शो निर्देशिका में कॉपी करने की कोशिश कर रहा हूं, तो क्या समाधान अभी भी काम कर रहे हैं?

संपादित करें 2: मेरी समस्या यह थी कि मैं कमांड _में शिफ्ट करने के अपने पहले विकल्प से पहले गायब था -exec। किसी के लिए भी जो इस बात के लिए उत्सुक है कि कमांड कमांड कैसे बनाएं, _और सब कुछ ठीक हो जाएगा:

find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2"' _ "{}" "$targetdir" \;

मैंने नीचे एक उत्तर स्वीकार किया है, क्योंकि यह एक ही कार्य को पूरा करता है, लेकिन अधिक कुशल और सुरुचिपूर्ण है।


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

ग्नू-खोजने और + के बजाय ";" के साथ, आप एक साथ कई तर्कों को भी ढूंढ सकते हैं। और आप -0 के साथ गुजरते हुए जटिल तर्क को बचाते हैं।
उपयोगकर्ता अज्ञात

@userunknown: मैं आपके जवाब के नीचे इसका जवाब दे रहा हूं।
जेएम बेकर

@user अज्ञात खैर, मैं इस कोड को प्यार करता हूं। यह कम से कम पूरी तरह से POSIX- अनुरूप है और मशीन पर किसी भी GNU सामान के बिना काम करेगा। ऐसे समय होते हैं जब आपको इसकी आवश्यकता होती है, विशेष रूप से काम पर सर्वर पर।
वाक्यविन्यास

जवाबों:


6

आप एक विशिष्ट प्रकार की फ़ाइलों को एक विशिष्ट निर्देशिका में कॉपी करना चाहते हैं? यह सबसे अच्छा है xargs, और आपको इसकी आवश्यकता भी नहीं है sh। यह करने के लिए एक अधिक उपयुक्त तरीका है, इसे और अधिक कुशलता से चलाना चाहिए।

find "$sourcedir" -type f -name "*.type" | xargs cp -t targetdir

यदि आपको विशेष फ़ाइल नामों को संभालने की आवश्यकता है, तो NULLअपने सेपरेटर के रूप में उपयोग करें

find "$sourcedir" -type f -name "*.type" -print0 | xargs -0 cp -t "$targetdir"

1
2 मामले के लिए, जोड़ने के लिए भूल नहीं है -print0करने के लिए findऔर -0करने के लिएxargs
SiegeX

@ घेराबंदी, पहले से ही कर रहा था, इससे पहले कि मैं आपकी टिप्पणी पर गौर करता।
जेएम बेकर

इसके अलावा, NULLयदि आप उपयोग नहीं करते हैं '{}', तो यह महत्वपूर्ण नहीं है जब आप नहीं करते हैं। POSIXअनुपालन के अलावा एक दूसरे के बीच वास्तविक लाभ , प्रदर्शन है।
जेएम बेकर

6

आपको {}शेल पर एक तर्क के रूप में पास करने की आवश्यकता है , फिर प्रत्येक आर्ग पर लूप करें।

find "$sourcedir" -type f -name "*.type" -exec sh -c 'for f; do cp "$f" "$0"; done' "$targetdir" {} +

नोट : जिस तरह से यह काम करता है कि शेल के लिए पहला arg शेल का नाम है , हम इस नाम के रूप में पास करके इसका फायदा उठा सकते हैं $targetdirऔर फिर $0उस टारगेट तक पहुंचने के लिए शेल स्क्रिप्ट के अंदर विशेष पैरामीटर का उपयोग कर सकते हैं।


1
"$targetdir"एकल उद्धरण के अंदर विस्तारित नहीं है।
enzotib

5

यदि आप xargs के चर्च में विश्वास नहीं करते हैं:

find "$sourcedir" -type f -name "*.mp3" -exec cp -t "$targetdir" {} +

स्पष्टीकरण:

cp -t a b c d 

लक्ष्य के लिए b, c और d की प्रतियां dir a।

-exec cmd {} +

एक ही बार में फ़ाइलों के एक बड़े समूह पर कमांड को आमंत्रित करता है, एक के बाद एक नहीं (जो मानक है, यदि आप ";"इसके बजाय उपयोग करते हैं +)। यही कारण है कि टारगेट को आगे की ओर खींचना है और इसे स्पष्ट रूप से लक्ष्य के रूप में चिह्नित करना है।

यह ग्नू-खोज के लिए काम करता है और हो सकता है कि यह अन्य कार्यान्वयनों के लिए न हो। बेशक यह -t -flag पर भी निर्भर करता है।

TechZilla बेशक अभी तक सही है, क्योंकि shcp को इनवाइट करने की जरूरत नहीं है।

यदि आप उपयोग नहीं करते हैं xargs, जो कि ज्यादातर समय के साथ संयोजन में अनावश्यक है find, तो आपको ध्वज -print0और -0ध्वज सीखने से बचाया जाता है ।


1
Obvisouly, जो विधि किसी को पसंद कर सकते हैं somwhat व्यक्तिपरक है। उस के साथ कहा, वहाँ अभी भी उपयोग करने के लिए मौजूद कारण है xargs। सबसे बड़ा उदाहरण, अगर आपको फाइलें नहीं मिल रही हैं तो क्या होगा? मैं forहर समय सामान्य छोरों के स्थान पर xargs का उपयोग करता हूं , जो findकि बहुत छोटा है। इसके अतिरिक्त, findकेवल यह समर्थन करता है कि +यदि आप GNU का उपयोग कर रहे हैं find, तो यह POSIX में परिभाषित नहीं है। इसलिए जबकि आपको findअकेले रहना पसंद करना चाहिए , यह वह सब कुछ नहीं करता है जो xargs करता है। जब आप GNU पर विचार करते हैं तो xargsआपको वह भी मिलता है -Pजो मल्टी-कोर करता है। इसकी xargsपरवाह किए बिना सीखने लायक है ।
जेएम बेकर

विषय पर बोलते हुए, मेरी राय स्पष्ट रूप से भिन्न होती है। दूसरी ओर, आपका उत्तर भी सही है। यह उपलब्ध कुछ सर्वश्रेष्ठ समाधानों में से एक है।
जेएम बेकर

@TechZilla: मुझे उम्मीद है कि इस साइट को फिर से याद करने की जरूरत है, जब खोज समानांतर आह्वान का समर्थन करना शुरू करती है। :) कॉपी / मूविंग के साथ ज्यादातर मामलों में, डिस्क की गति सीमित कारक होगी, लेकिन SSD चित्र बदल सकते हैं। आप सही कह रहे हैं, कि गैर-जीएनयू-समाधान प्रदान करने के लिए एक अच्छी बात है। और, खोज-समाधान वस्तुनिष्ठ रूप से कम, सरल है, और केवल दो प्रक्रियाओं का उपयोग करता है।
उपयोगकर्ता अज्ञात

0
read -p "SOURCE: " sourcedir
read -p "TYPE: " type
read -p "TARGET: " targetdir
find -L $sourcedir -iname "*.$type" -exec cp -v {} $targetdir \;

3
अपने समाधान के कुछ स्पष्टीकरण को जोड़ने पर विचार करें।
हेलोजगॉस्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.