खोज: गायब तर्क


206

मुझे आज एक कमांड के साथ मदद मिली थी, लेकिन यह काम नहीं कर रहा है। यह आदेश है:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {}\;

खोल देता है

find: missing argument to `-exec'

जो मैं मूल रूप से करने की कोशिश कर रहा हूं वह एक निर्देशिका के माध्यम से पुनरावर्ती रूप से जाना जाता है (यदि इसकी अन्य निर्देशिकाएं हैं) और .rmफ़ाइल प्रकारों पर ffmpeg कमांड चलाएं और उन्हें .mp3फ़ाइल प्रकारों में परिवर्तित करें । एक बार यह हो जाने के बाद, उस .rmफ़ाइल को हटा दें जिसे अभी परिवर्तित किया गया है।

मैं इस पर किसी भी मदद की सराहना करता हूं।

जवाबों:


340

एक -execकमांड को एक के साथ समाप्त किया जाना चाहिए ;(ताकि आपको आमतौर पर टाइप करने \;या ';'शेल द्वारा व्याख्या से बचने की आवश्यकता हो ) या ए +। अंतर यह है कि ;, कमांड को एक बार प्रति फ़ाइल के साथ +कहा जाता है, इसके साथ , इसे केवल कुछ समय के लिए संभव के रूप में कहा जाता है (आमतौर पर एक बार, लेकिन कमांड लाइन के लिए अधिकतम लंबाई होती है, इसलिए इसे सभी फ़ाइल नाम के साथ विभाजित किया जा सकता है) । इस उदाहरण को देखें:

$ cat /tmp/echoargs
#!/bin/sh
echo $1 - $2 - $3
$ find /tmp/foo -exec /tmp/echoargs {} \;
/tmp/foo - -
/tmp/foo/one - -
/tmp/foo/two - -
$ find /tmp/foo -exec /tmp/echoargs {} +
/tmp/foo - /tmp/foo/one - /tmp/foo/two

आपकी कमांड में दो त्रुटियां हैं:

सबसे पहले, आप उपयोग करते हैं {};, लेकिन ;स्वयं का एक पैरामीटर होना चाहिए।

दूसरा, कमांड का अंत होता है &&। आपने निर्दिष्ट "रन खोजें, और यदि वह सफल था, तो नाम वाली फ़ाइल को हटा दें {};।" यदि आप -execकमांड में शेल सामान का उपयोग करना चाहते हैं , तो आपको इसे शेल में स्पष्ट रूप से चलाने की आवश्यकता है, जैसे -exec sh -c 'ffmpeg ... && rm'

हालाँकि आपको बैश कमांड के अंदर {} को नहीं जोड़ना चाहिए, यह विशेष वर्ण होने पर समस्याएं पैदा करेगा। इसके बजाय, आप खोल के बाद अतिरिक्त पैरामीटर पास कर सकते हैं -c command_string(देखें man sh):

$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)

आप देखते हैं कि $पहले उदाहरण में शेल द्वारा चीज़ का मूल्यांकन किया गया है। कल्पना कीजिए कि $(rm -rf /):-) नामक एक फाइल थी

(साइड नोट: इसकी -जरूरत नहीं है, लेकिन कमांड के बाद पहला वैरिएबल वेरिएबल को सौंपा गया है $0, जो कि एक विशेष वेरिएबल है, जिसमें सामान्य रूप से प्रोग्राम का नाम रन और सेटिंग होता है, जो कि पैरामीटर के लिए थोड़ा अशुद्ध है, हालांकि यह जीता है 'शायद यहाँ कोई नुकसान नहीं पहुँचाता, इसलिए हम इसे सिर्फ -और शुरू करने के लिए निर्धारित करते हैं $1।'

तो आपकी आज्ञा कुछ इस तरह हो सकती है

find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;

लेकिन एक बेहतर तरीका है। समर्थन andऔर पाते हैं or, तो आप की तरह सामान कर सकते हैं find -name foo -or -name bar। लेकिन यह भी साथ काम करता है -exec, जो सही मूल्यांकन करता है यदि आदेश सफलतापूर्वक बाहर निकलता है, और यदि नहीं तो गलत है। इस उदाहरण को देखें:

$ ls
false  true
$ find * -exec {} \; -and -print
true

यह केवल प्रिंट चलाता है यदि कमांड सफलतापूर्वक था, जो इसके लिए किया था, trueलेकिन इसके लिए नहीं false

तो आप एक के साथ जंजीर के दो निष्पादन विवरणों का उपयोग कर सकते हैं -and, और यह केवल बाद वाले को निष्पादित करेगा यदि पूर्व सफलतापूर्वक चलाया गया था।


3
लगता है कि मैरियन की लाइन "the, is a arg on it’s own" है, जिसने मेरे लिए, लाइटबल्ब वार और मेरे कोड नमूने के लिए यह किया। धन्यवाद।
pjammer

3
यह सबसे अच्छा विवरण है जिसके बारे में मैंने पढ़ा है -exec पर। यह बेहद शक्तिशाली है लेकिन मुझे हमेशा इसके लिए सही वाक्यविन्यास करना मुश्किल लगता है। इससे कुछ चीजें बहुत साफ हो गईं। विशेष रूप से अलग शेल में कमांड लपेटना। अच्छा लगा। धन्यवाद।
यूरोस्पोफर

3
ध्यान दें कि -andऔर -orपोर्टेबल नहीं हैं। POSIX निर्दिष्ट करता है -aऔर-o , और वास्तव -aमें हमेशा माना जाता है (इसलिए आवश्यक नहीं)।
ग्नौरफ_गनीउरफ़

इसके अलावा टर्मिनेटर से पहले एक स्थान होना चाहिए। पूर्व "\;"काम नहीं करता है लेकिन " \;"करता है
frmdstryr

56

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

find . -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 \; -exec rm {} \;

यकीन नहीं होता कि इसे डिलीट करने के लिए फाइल का वैरिएबल मिलेगा? किसी को पता है कि क्या यह मामला है?
Abs

7
ऐसी चीजों का परीक्षण करने के लिए बस echoकमांड्स से पहले जोड़ें और देखें कि यह क्या करता है।
मैरियन

2
@Marian, echoकाफी अविश्वसनीय है - आप के बीच अंतर नहीं बता सकता echo "one argument"और echo one argument(के बाद उत्पादन झूठी जा रहा है, के रूप में यह वास्तव में गुजर रहा है echoदो पूरी तरह अलग तर्क)। कुछ ऐसा करने के लिए बेहतर है -exec bash -c 'printf "%q " "$@"' _ ffmpeg -i {} -sameq {}.mp3 \; -printf '\n', जो आउटपुट को इस तरह से प्रिंट करेगा जो गैर-वर्णों के वर्णों को दृश्यमान बनाता है ताकि आप डॉस की नई रूपरेखाओं और अन्य विषमताओं का पता लगा सकें।
चार्ल्स डफी

52

प्रत्येक \ से पहले एक स्थान डालने का प्रयास करें;

काम करता है:

find . -name "*.log" -exec echo {} \;

काम नहीं करता है:

find . -name "*.log" -exec echo {}\;

1
यह मुझे बहुत बार यात्रा करता है। इन दिनों में से एक, मैं डिफ़ॉल्ट रूप से एक स्थान जोड़ूंगा।
हार्पर्विल

मेरे लिए यह विंडोज 7 के तहत सिगविन में बस विपरीत काम करता है: \ पहले कोई स्थान नहीं; अंतरिक्ष के साथ काम करता है - नहीं। लेकिन अगर मैं पहले अंतरिक्ष के साथ, हटा दें; यह काम करता है, और अंतरिक्ष के बिना पहले; यह नहीं है, जिस तरह से यहाँ वर्णित है।
वेबकॉमर

7

आपकी जानकारी के लिए:
मैंने अभी-अभी Cygwin सिस्टम पर "find -exec" कमांड का उपयोग करने की कोशिश की है (Windows पर UNIX का अनुकरण), और ऐसा लगता है कि अर्धविराम से पहले बैकस्लैश को हटा दिया जाना चाहिए:
find ./ -name "blabla" -exec wc -l {} ;


मैं वास्तव में उलझन में है। find /etc/nginx -name '*.conf' -exec echo {} ;और find /etc/nginx -name '*.conf' -exec echo {}\;एक ही परिणाम दिया। :(
किर्बी

मैं बैश शेल चला रहा हूं जो विंडोज के लिए गिट के साथ आता है, और डस्टिन काउल्स का जवाब मेरे लिए काम करता है। दूसरे शब्दों में: कोई उद्धरण नहीं, बैकस्लैश अर्धविराम से बच गया, अंतरिक्ष के बाद {}
मैमकॉन

अर्थ में कोई अंतर नहीं है, लेकिन कुछ मामलों में आपको बैकस्लैश डालने की आवश्यकता होती है, कुछ मामलों में आप इसे नहीं डाल सकते हैं, और फिर अन्य मामलों में आप चुन सकते हैं।
डोमिनिकन

2

जैसे ही किसी को अमेज़ॅन ओप्सवर्क्स शेफ बैश स्क्रिप्ट में एक समान "मिसिंग-एक्ससेक आर्ग्स" दिखाई देता है, मुझे बचने के लिए एक और बैकस्लैश जोड़ने की जरूरत थी;

bash 'remove_wars' do
  user 'ubuntu'
  cwd '/'
  code <<-EOH
    find /home/ubuntu/wars -type f -name "*.war" -exec rm {} \\;
  EOH
  ignore_failure true
end

2

इसके अलावा, अगर किसी और के पास "खोज: लापता तर्क -exec" है तो इससे मदद मिल सकती है:

कुछ गोले में आपको भागने की जरूरत नहीं है, यानी आपको "" के सामने "" की जरूरत नहीं है।

find <file path> -name "myFile.*" -exec rm - f {} ;

2
यहां ;उद्धृत या बच नहीं जाने का मतलब यह है कि इसे शेल द्वारा खाया जा सकता है, द्वारा नहीं पढ़ा जाता है find। इसके अलावा, -fऔर - fदो अलग चीजें हैं।
चार्ल्स डफी


0

{} और && दोनों कमांड लाइन द्वारा विस्तारित होने के कारण समस्याएं पैदा करेंगे। मैं सुझाव देना चाहूंगा:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i \{} -sameq \{}.mp3 \; -exec rm \{} \;

यदि निष्पादन में पहला कमांड सफल होता है और निष्पादन में दूसरा कमांड निष्पादित होता है, तो क्या उसके पास {}सही फ़ाइल को हटाने के लिए चर तक पहुंच होगी ?
ABS

तुम क्या करने के {}लिए फैलता है? जब तक कि इसमें दो डॉट या कॉमा न हों, जो जैसा है वैसा ही रहेगा।
मैरियन

0

आपको बीच में एक जगह रखनी होगी {} और के\;

तो कमांड इस तरह होगी:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {} \;

-4

यदि आप अभी भी "ढूंढ रहे हैं: लापता तर्क को -exec" उद्धरणों में निष्पादित तर्क को लपेटने का प्रयास करें।

find <file path> -type f -exec "chmod 664 {} \;"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.