क्यों -exec mv {} ./target/ + काम नहीं करता है?


98

मैं वास्तव में क्या जानना चाहते हैं {} \;और {} \+और | xargs ...करते हैं। कृपया इन्हें स्पष्टीकरण के साथ स्पष्ट करें।

नीचे 3 कमांड रन और आउटपुट एक ही परिणाम लेकिन पहली कमांड में थोड़ा समय लगता है और प्रारूप भी थोड़ा अलग होता है।

find . -type f -exec file {} \;
find . -type f -exec file {} \+
find . -type f | xargs file

ऐसा इसलिए है क्योंकि 1 fileआदेश से आने वाली हर फ़ाइल के लिए कमांड चलाता है find। तो, मूल रूप से यह इस प्रकार चलता है:

file file1.txt
file file2.txt

लेकिन बाद वाले 2 -execकमांड को फाइल कमांड के साथ ढूंढते हैं, जैसे नीचे दी गई सभी फाइलों के लिए:

file file1.txt file2.txt

फिर मैं निम्नलिखित कमांड चलाता हूं, जिसमें पहला बिना किसी समस्या के चलता है, लेकिन दूसरा त्रुटि संदेश देता है।

find . -type f -iname '*.cpp' -exec mv {} ./test/ \;
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+ #gives error:find: missing argument to `-exec'

कमांड के साथ {} \+, यह मुझे त्रुटि संदेश देता है

find: missing argument to `-exec'

ऐसा क्यों है? किसी को भी समझा सकता हूँ कि मैं क्या गलत कर रहा हूँ?


असली सवाल सरल है, पहला काम क्यों करता है और दूसरा क्यों नहीं? (१) पाते हैं। -type f -iname ' .cpp' -exec mv {} / .est / \; (२) खोजना। -टाइप f -iname ' .cpp' -exec mv {} .test/ \ +
शहादत हुसैन

जवाबों:


185

मैन्युअल पृष्ठ (या ऑनलाइन जीएनयू मैनुअल ) काफी सब कुछ बताते हैं।

find -exec कमांड {} \;

प्रत्येक परिणाम के लिए, command {}निष्पादित किया जाता है। सभी घटनाओं {}को फ़ाइल नाम से बदल दिया जाता है। ;शेल की व्याख्या करने से रोकने के लिए एक स्लैश के साथ उपसर्ग किया जाता है।

find -exec कमांड {} +

प्रत्येक परिणाम को commandबाद में जोड़ा जाता है और निष्पादित किया जाता है। कमांड लंबाई की सीमा को ध्यान में रखते हुए, मुझे लगता है कि इस कमांड को अधिक बार निष्पादित किया जा सकता है, मैनुअल पेज मेरा समर्थन कर रहा है:

कमांड की कुल संख्या का मिलान की गई फ़ाइलों की संख्या से बहुत कम होगा।

मैनुअल पृष्ठ से इस उद्धरण पर ध्यान दें:

कमांड लाइन को उसी तरह बनाया गया है जिस तरह से xargs अपनी कमांड लाइन बनाता है

इसीलिए व्हॉट्सएप के अलावा {}और +किसी भी पात्र को अनुमति नहीं है । +यह पता लगाता है कि तर्कों को उसी तरह कमांड में जोड़ा जाना चाहिए xargs

समाधान

सौभाग्य से, GNU कार्यान्वयन mvलक्ष्य निर्देशिका को एक तर्क के रूप में स्वीकार कर सकता है, -tया तो पैरामीटर के साथ --target। इसका उपयोग होगा:

mv -t target file1 file2 ...

आपकी findआज्ञा बन जाती है:

find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+

मैनुअल पेज से:

-exec कमांड;

निष्पादित आदेश; सच है अगर 0 स्थिति वापस आ गई है। निम्नलिखित सभी तर्क खोजने के लिए कमांड के तर्क दिए जाते हैं जब तक कि एक तर्क जिसमें `; 'शामिल नहीं है; सामना किया है। स्ट्रिंग `{} 'को वर्तमान फ़ाइल नाम से बदल दिया जाता है जिसे हर जगह संसाधित किया जाता है यह कमांड के तर्कों में होता है, न कि केवल उन तर्कों में जहां यह अकेला है, जैसा कि कुछ संस्करणों में पाया जाता है। इन दोनों निर्माणों को शेल द्वारा विस्तार से बचाने के लिए (`\ 'के साथ) भाग जाने या उद्धृत करने की आवश्यकता हो सकती है। -Exec विकल्प के उपयोग के उदाहरणों के लिए EXAMPLES अनुभाग देखें। निर्दिष्ट आदेश प्रत्येक मिलान की गई फ़ाइल के लिए एक बार चलाया जाता है। कमांड को शुरुआती डायरेक्टरी में निष्पादित किया जाता है। -Exec कार्रवाई के उपयोग के आसपास सुरक्षा संबंधी समस्याएं नहीं हैं; आपको इसके बजाय -execdir विकल्प का उपयोग करना चाहिए।

-exec कमांड {} +

-Exec कार्रवाई का यह संस्करण चयनित फ़ाइलों पर निर्दिष्ट कमांड चलाता है, लेकिन कमांड लाइन अंत में प्रत्येक चयनित फ़ाइल नाम को जोड़कर बनाया गया है; कमांड की कुल संख्या का मिलान की गई फ़ाइलों की संख्या से बहुत कम होगा। कमांड लाइन को उसी तरह बनाया गया है जिस तरह से xargs अपनी कमांड लाइन बनाता है। कमांड के भीतर `{} 'के केवल एक उदाहरण की अनुमति है। कमांड को शुरुआती डायरेक्टरी में निष्पादित किया जाता है।


1
मुझे पता है कि यह कैसे काम करता है, मैं कई बार इस मैनुअल से गुजरा हूं, लेकिन मुझे {} + का उपयोग करने के लिए त्रुटि संदेश मिला है, हालांकि {} \ के लिए काम करता है; और मैं खिड़कियों में Cygwin का उपयोग कर रहा हूं।
शहादत हुसैन

1
@ शहादत: क्या आपने "मैनुअल पेज से" से पहले भाग पढ़ा है? आप डाल दिया है ./test/के बीच {}और +, लेकिन कोई गैर-सफ़ेद पात्रों इन के बीच की अनुमति है।
लेकेनस्टाइन

ru यह कहते हुए कि मुझे {} और + के बीच में / test / नहीं लगाना चाहिए। फिर एमवी कमांड कैसे काम करेगा; mv को स्रोत की आवश्यकता है जो {} है और गंतव्य की आवश्यकता है जो / .est / और समाप्ति के साथ + है। क्या आप कृपया वही लिख सकते हैं जो आप सही समझते हैं?
शहादत हुसैन

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

1
+आदेश थोड़ा अजीब AFAIU क्योंकि यह "अंत" में फ़ाइलों चिपक (और के स्थान पर नहीं है {}) तो क्यों का उपयोग कर {}यह भ्रामक है - सब पर। उस -tविकल्प के लिए धन्यवाद, जो मुझे नहीं पता था, ऐसा लगता है कि विकल्प को उस -exec +समस्या के समाधान के रूप में बनाया गया था !
e2-e4

6

मुझे मैक ओएसएक्स पर एक ही मुद्दे का सामना करना पड़ा , एक ज़ेडएस शेल का उपयोग करते हुए : इस मामले में कोई -tविकल्प नहीं है mv, इसलिए मुझे एक और समाधान खोजना पड़ा। हालाँकि निम्नलिखित कमांड सफल रही:

find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;

राज़ ब्रेसिज़ को उद्धृत करना था । execआदेश के अंत में ब्रेसिज़ की आवश्यकता नहीं है ।

मैंने Ubuntu 14.04 ( BASH और ZSH गोले के साथ) के तहत परीक्षण किया , यह एक ही काम करता है।

हालांकि, +साइन का उपयोग करते समय , यह वास्तव में लगता है कि इसे execकमांड के अंत में होना चाहिए ।


{}जरूरतों में उद्धृत किया जाना है fishऔर rcगोले, लेकिन नहीं में zsh, bashऔर न ही बॉर्न या csh परिवारों के किसी भी अन्य गोले।
स्टीफन चेज़लस

@StephaneChazelas हां, एक उबंटू के तहत सेवानिवृत्त bash, वास्तव में उद्धरण अशिष्ट नहीं हैं। उत्सुकता से, मेरे पास एक मुद्दा था अगर उन्हें मैकओएस (उपयोग zsh) के तहत उद्धृत नहीं किया गया था । लेकिन मैं एक मैक पर फिर से कोशिश करने के लिए नहीं है ...
arvymetal

3

के मानक समकक्ष find -iname ... -exec mv -t dest {} +के लिए findकार्यान्वयन कि समर्थन नहीं करते -inameया mvकार्यान्वयन कि समर्थन नहीं करते -tफिर से आदेश तर्कों को एक खोल उपयोग करने के लिए है:

find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
  exec mv "$@" /dest/dir/' sh {} +

का उपयोग करके -name '*.[cC][pP][pP]', हम यह तय करने के लिए वर्तमान स्थान पर निर्भरता से भी बचते हैं कि अपरकेस संस्करण क्या है cया नहीं p

ध्यान दें +, इसके विपरीत ;किसी भी शेल में विशेष नहीं है , इसलिए उद्धृत करने की आवश्यकता नहीं है (हालांकि उद्धृत करने से कोई नुकसान नहीं होगा, सिवाय शेल के साथ जैसे rcकि \एक उद्धरण ऑपरेटर के रूप में समर्थन नहीं करते हैं )।

अनुगामी /में /dest/dir/इतना है कि है mvबजाय का नाम बदलने का एक त्रुटि के साथ विफल foo.cppकरने के लिए /dest/dirमामले में जहां केवल एक cppफ़ाइल मिला था और /dest/dirमौजूद नहीं था या एक निर्देशिका (या निर्देशिका के लिए सिमलिंक) नहीं था।


+1 ... इन-शेल ऑपरेशन एक कमांड को निष्पादित करने के लिए प्रारंभिक के रूप में वास्तव में उपयोग के विभिन्न मामलों के लिए उपयोगी है ... अच्छा।
Cbhihe

0
find . -name "*.mp3" -exec mv --target-directory=/home/d0k/Музика/ {} \+

कृपया अपने उत्तर में कुछ स्पष्टीकरण जोड़ें, ताकि अन्य लोग इससे सीख सकें
निको हसे

आपको उस प्रश्न का उत्तर देने की आवश्यकता है, जिसने स्पष्टीकरण के लिए पूछा था। कोड-केवल एक उत्तर नहीं है।
लाजोस अरपाद

-1

नहीं, के बीच का अंतर +और \;उलट होना चाहिए। +फ़ाइलों को निष्पादित कमांड के अंत में जोड़ता है, फिर निष्पादन कमांड \;चलाता है और प्रत्येक फ़ाइल के लिए कमांड चलाता है।

समस्या यह find . -type f -iname '*.cpp' -exec mv {} ./test/ \+होनी चाहिए कि find . -type f -iname '*.cpp' -exec mv {} ./test/ + वह बच जाए या उसे समाप्त कर दे+

xargs जिसका मैंने लंबे समय से उपयोग नहीं किया है लेकिन मुझे लगता है कि यह + की तरह काम करता है।


मैंने भी इसके साथ प्रयास किया लेकिन मुझे वही त्रुटि संदेश मिला। इसके अलावा, हर जगह मुझे केवल + का उपयोग करने के लिए मिला, लेकिन मेरी साइबरविन में मुझे काम करने के लिए \ + या "+" का उपयोग करना होगा।
शहादत हुसैन

ओह, यह एक साइबर माहौल है। क्षमा करें, मुझे नहीं पता, मैं साइबर शेल का उपयोग नहीं करता, मैं सिर्फ एक * निक्स का उपयोग करता हूं।
माइक रामिरेज़

1
@ शहादत हुसैन कोशिश करते हैं कि -name "*.cpp"मैं मुश्किल से इस्तेमाल न करूं जब तक कि मैं कुछ मुश्किल रीगेक्स खोज नहीं करना चाहता, जैसे कि '??? काम। * \ _। सीपीपी'
माइक रामिरेज़

1
@ माइक: मुझे लगता है कि आप -inameऔर के बीच के अंतर को गलत समझते हैं -name-inameके मामले-असंवेदनशील संस्करण है -nameऔर नियमित अभिव्यक्ति से निपटने में कोई अंतर नहीं है। मैं पोस्ट करने से पहले आदेशों का प्रयास करने का सुझाव देता हूं, आपका आदेश मेरे शेल में भी विफल रहता है।
लेकेनस्टाइन 20

1
@Lekensteyn यह पहले से ही आपकी टिप्पणी से पहले स्थापित किया गया था। मुझे लगा कि मैंने आपकी पोस्ट से पहले शहादत को स्वीकार कर लिया है, यह एक सरल "ठीक" था। नहीं, मैंने इसे मैन्युअल रूप से नहीं चलाया था, मैंने इसे अपने सिर के ऊपर से किया था और शायद ही कभी regex खोज के उस रूप का उपयोग किया हो। यह सिर्फ एक 'मदद कर सकता है' टाइप चीज थी।
माइक रामिरेज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.