2012-05-29 24 views
31

में स्ट्रिंग की जगह:संशोधित जब मैं <code>xargs</code> उपयोग कर रहा हूँ कभी कभी मैं स्पष्ट रूप से जगह स्ट्रिंग का उपयोग करने की जरूरत नहीं xargs

find . -name "*.txt" | xargs rm -rf 

अन्य मामलों में, मैं क्रम जैसी चीज़ें करने में जगह स्ट्रिंग निर्दिष्ट करना चाहते हैं:

find . -name "*.txt" | xargs -I '{}' mv '{}' /foo/'{}'.bar 

पिछला आदेश /foo में वर्तमान निर्देशिका के अंतर्गत सभी पाठ फ़ाइलों को स्थानांतरित होगा और यह सभी फाइलों को विस्तार bar संलग्न कर देगा।

यदि प्रतिस्थापन स्ट्रिंग में कुछ पाठ जोड़ने की बजाय, मैं उस स्ट्रिंग को संशोधित करना चाहता था जैसे कि मैं फ़ाइलों के नाम और विस्तार के बीच कुछ टेक्स्ट डाल सकता हूं, मैं यह कैसे कर सकता हूं? उदाहरण के लिए, मान लीजिए कि मैं पिछले उदाहरण की तरह ही करना चाहता हूं, लेकिन फ़ाइलों का नाम बदलकर <name>.txt से /foo/<name>.bar.txt (/foo/<name>.txt.bar के बजाय) किया जाना चाहिए।

अद्यतन: मैं एक समाधान खोजने के लिए प्रबंधन:

find . -name "*.txt" | xargs -I{} \ 
    sh -c 'base=$(basename $1) ; name=${base%.*} ; ext=${base##*.} ; \ 
      mv "$1" "foo/${name}.bar.${ext}"' -- {} 

लेकिन मुझे आश्चर्य है कि अगर वहाँ एक छोटी/बेहतर समाधान है।

+1

नहीं है, सिवाय इसके कि मैं और अधिक के हवाले से 'mv" $ 1 "" foo/$ {नाम} .bar का प्रयोग करेंगे $ {ext} "' और तुम कर सकते हो '। बेसनाम 'इस तरह: 'आधार = $ {1 ## * /}'। आपको अपना समाधान उत्तर के रूप में पोस्ट करना चाहिए और इसे स्वीकार करना चाहिए। –

+0

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

+1

मुझे लगता है कि यदि आपका फ़ाइल नाम लाइन पर आखिरी चीज है, तो आपको कमांड लाइन में -आई {} और न ही {} की आवश्यकता नहीं है। (ध्यान दें कि xargs का उद्देश्य उद्देश्य समूह के लिए है, इसलिए यदि आप 1 xargs 'तर्क आमंत्रण के अंत में कई चीजें नहीं चाहते हैं तो आपको "-l 1" (या xargs के कुछ संस्करणों के लिए -एल 1) की आवश्यकता है। -आई {} का तात्पर्य है- 1, इसलिए यही कारण है कि यह भी काम करता है।) –

उत्तर

12

इस तरह के मामलों में, एक while पाश अधिक पठनीय होगा:

find . -name "*.txt" | while IFS= read -r pathname; do 
    base=$(basename "$pathname"); name=${base%.*}; ext=${base##*.} 
    mv "$pathname" "foo/${name}.bar.${ext}" 
done 

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

+0

हाँ, मुझे पता है कि यह "समस्या" है। असल में मैंने जो उदाहरण पोस्ट किया है वह मूर्खतापूर्ण है। मैंने अभी अपने प्रश्न में एक साधारण उदाहरण दिखाने के लिए इसे बनाया है, इसलिए कोई समस्या नहीं :) – betabandido

+1

उस फ़ाइल नामों को संभालने के लिए जिसमें इसकी एक नई लाइन है, इसका उपयोग करें: 'ढूंढें। -नाम "* .txt" -print0 | जबकि read -r -d 'पथनाम; करें ... ' – Cem

+2

ध्यान दें कि यदि आप' --max-procs' का उपयोग कर xargs को समानांतर करने का प्रयास कर रहे हैं तो यह (धारावाहिक) दृष्टिकोण काम नहीं करेगा। – g33kz0r

2

यदि आपको बैश/sh के अलावा कुछ और उपयोग करने की अनुमति है, और यह सिर्फ एक फैंसी "एमवी" के लिए है ... तो आप आदरणीय "rename.pl" स्क्रिप्ट का प्रयास कर सकते हैं। मैं इसे हर समय विंडोज़ पर लिनक्स और साइगविन पर उपयोग करता हूं।

http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html

rename.pl 's/^(.*?)\.(.*)$/\1-new_stuff_here.\2/' list_of_files_or_glob 

तुम भी वास्तव में यह कर के बिना, यह आपको बता यह क्या किया होता है करने के लिए rename.pl के लिए एक "-p" पैरामीटर का उपयोग कर सकते हैं।

मैंने बस अपने सी:/बिन (साइगविन/विंडोज वातावरण) में निम्नलिखित की कोशिश की। मैंने "-पी" का उपयोग किया ताकि यह थूक जाए कि यह क्या होगा। यह उदाहरण सिर्फ आधार और एक्सटेंशन को विभाजित करता है, और उनके बीच एक स्ट्रिंग जोड़ता है।

perl c:/bin/rename.pl -p 's/^(.*?)\.(.*)$/\1-new_stuff_here.\2/' *.bat 

rename "here.bat" => "here-new_stuff_here.bat" 
rename "htmldecode.bat" => "htmldecode-new_stuff_here.bat" 
rename "htmlencode.bat" => "htmlencode-new_stuff_here.bat" 
rename "sdiff.bat" => "sdiff-new_stuff_here.bat" 
rename "widvars.bat" => "widvars-new_stuff_here.bat" 
+0

आपके उत्तर के लिए धन्यवाद! हालांकि, एमवी' उदाहरण सिर्फ एक उदाहरण था। मुझे कई अन्य स्थितियों में कुछ ऐसा करने की ज़रूरत है, इसलिए मुझे लगता है कि 'rename.pl' उन मामलों के लिए काम नहीं करेगा। – betabandido

+0

ठीक है, हाँ और नहीं; आप आसानी से rename.pl को संशोधित कर सकते हैं * नहीं * वास्तव में एक फ़ाइल का नाम बदलें, लेकिन इसके साथ कुछ और करें। जैसा कि आप देख सकते हैं, "-p" पैरामीटर के साथ, यह बिल्कुल नाम नहीं बदलता है, लेकिन केवल परिवर्तन के परिणाम प्रिंट करता है। आप कई अन्य चीजों को करने के आधार के रूप में उस स्क्रिप्ट का उपयोग कर सकते हैं, और जो तर्क वह लेता है वह मनमाने ढंग से perl कोड है, जो बेहद शक्तिशाली है। लेकिन फिर भी आप निश्चित रूप से स्वागत करते हैं। –

9

आप जीएनयू समानांतर http://www.gnu.org/software/parallel/ स्थापित आप ऐसा कर सकते हैं:

find . -name "*.txt" | parallel 'ext="{/}" ; mv -- {} foo/{/.}.bar.${ext##*.}' 

आप जीएनयू समानांतर स्थापित कर सकते हैं बस द्वारा:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel 
chmod 755 parallel 
cp parallel sem 

घड़ी जीएनयू समानांतर के लिए परिचय वीडियो अधिक जानने के लिए: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

+2

मैं जीएनयू समानांतर 'xargs' से अधिक अनुशंसा करता हूं, यह अधिक शक्तिशाली और लचीला है। इसकी स्थापना के लिए, मैं दृढ़ता से सुझाव देता हूं कि आप अपने वितरण के पैकेज मैनेजर (जैसे 'सुडो एपीटी-इंस्टाल समानांतर') या समांतर की अनुशंसित इंस्टॉल प्रक्रिया का उपयोग करें (http://git.savannah.gnu.org/cgit/parallel के अनुसार। गिट/पेड़/रीडमे): '(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash' – MestreLion

+1

@MestreLion कृपया कर्ल-पाइप-टू-शैल एंटी-पैटर्न की अनुशंसा न करें। 'Pi.dk' क्या है? मुझे उस डोमेन पर भरोसा क्यों करना चाहिए? 'gnu.org' कम से कम अधिक भरोसेमंद है। लेकिन न तो यूआरएल टीएलएस का उपयोग कर रहा है, और सबसे महत्वपूर्ण बात यह है कि कोई भी डाउनलोड किए गए क्रिप्टोग्राफिक हस्ताक्षर को सत्यापित नहीं करता है। सिफारिश करने का एकमात्र समाधान 'apt-get' है। – blujay

+0

जैसा कि आप देख सकते हैं कि pi.dk/3 क्रिप्टोग्राफ़िक हस्ताक्षर का सत्यापन करता है और यदि हस्ताक्षर मेल नहीं खाता है तो बंद हो जाता है। यदि आप इसे सीधे खोलने के लिए असहज महसूस करते हैं तो आप इसे फ़ाइल में सहेज सकते हैं, कोड का निरीक्षण कर सकते हैं और फिर इसे चला सकते हैं। –

18

निम्न आदेश xargs के साथ चाल कमांड बनाता है, '।' की दूसरी घटना को प्रतिस्थापित करता है। '.bar' के साथ, फिर मैक ओएसएक्स पर काम कर बैश के साथ आदेश निष्पादित करता है।

ls *.txt | xargs -I {} echo mv {} foo/{} | sed 's/\./.bar./2' | bash 
+1

डर्टे! मुझे यह पसंद है – g33kz0r

+0

यह एक साफ चाल है – Zerodf

7

यह संभव एक पास (जीएनयू में परीक्षण) में यह करने के लिए अस्थायी चर असाइनमेंट

find . -name "*.txt" | xargs -I{} sh -c 'mv "$1" "foo/$(basename ${1%.*}).new.${1##*.}"' -- {} 
+1

मैं जिस तरह से प्रतिस्थापन स्ट्रिंग का उपयोग खोल के लिए एक स्थितित्मक पैरामीटर के रूप में कर रहा हूं उससे प्यार करता हूं ताकि आप प्रतिस्थापन और विस्तार कर सकें। बहुत ही शांत। – GL2014

0

ऊपर @justaname द्वारा एक जवाब से प्रेरित होकर का उपयोग न करें, इस आदेश को जो पर्ल को शामिल किया गया है एक लाइनर यह करना होगा:

find ./ -name \*.txt | perl -p -e 's/^(.*\/(.*)\.txt)$/mv $1 .\/foo\/$2.bar.txt/' | bash