दिलचस्प पोस्ट
मैक पाठ / कोड संपादक क्या मैं अपना स्पष्ट प्रकार तुलनित्र इनलाइन निर्दिष्ट कर सकता हूं? WPF में उलटा बूलियन गुण कैसे बाँटें? वसंत CSRF टोकन काम नहीं करता है, जब अनुरोध भेजा जा रहा है तो एक बहु-अनुरोध अनुरोध है मैं एक ही तत्व पर पृष्ठभूमि-छवि और CSS3 के ढाल को कैसे जोड़ूं? संस्करण नियंत्रण (यानी उपवर्तन) दस्तावेज़ ट्रैकिंग में लागू है? GCC / clang विधानसभा आउटपुट से "शोर" को कैसे निकालना है? इंटेंट्स के माध्यम से ईमेल प्रोग्राम कैसे खोलें (लेकिन केवल एक ईमेल प्रोग्राम) जावास्क्रिप्ट के साथ यूआरएल पैरामीटर कैसे प्राप्त करें? एक सीएसवी को विभाजित करने के लिए रेगेक्स अजगर की सूची से मूल्य की एक सूची मिल रही है आवेदन के साथ सहयोगी फ़ाइल एक्सटेंशन यादृच्छिक रूप से ढूँढें और sed के माध्यम से फ़ाइलों का नाम बदलें एकाधिक फ़ील्ड के साथ डिफ़ॉल्ट रूप से एकाधिक खोज योग की गणना के बजाय दो नंबर जोड़कर उन्हें जोड़ता है

यादृच्छिक रूप से ढूँढें और sed के माध्यम से फ़ाइलों का नाम बदलें

मैं निर्देशिकाओं के एक समूह के माध्यम से जाना चाहता हूं और सभी फाइलों का नाम बदलना चाहता हूं जो _test.rb के अंत में _spec.rb में समाप्त होने के बजाय ऐसा कुछ है जो मैंने कभी नहीं सोचा है कि बाश के साथ कैसे करना है, इस बार मैंने सोचा कि मैं इसे पकड़े जाने के लिए कुछ प्रयास करना चाहता हूं। मैं अभी तक थोड़ी देर तक आ गया हूं, मेरा सबसे अच्छा प्रयास है:

find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` \; 

NB: exec के बाद एक अतिरिक्त गूंज है, ताकि कमांड को चलाने के बजाय प्रिंट किया जाता है, जबकि मैं इसे परीक्षण कर रहा हूं।

जब मैं इसे चलाने के लिए प्रत्येक मिलान फ़ाइल नाम के लिए आउटपुट है:

 mv original original 

यानी एसएडी द्वारा प्रतिस्थापन खो दिया गया है। चाल क्या है?

वेब के समाधान से एकत्रित समाधान "यादृच्छिक रूप से ढूँढें और sed के माध्यम से फ़ाइलों का नाम बदलें"

यह इसलिए होता है क्योंकि sed स्ट्रिंग {} इनपुट के रूप में प्राप्त करता है, जैसा कि इसके साथ सत्यापित किया जा सकता है:

 find . -exec echo `echo "{}" | sed 's/./foo/g'` \; 

जो निर्देशिका में प्रत्येक फ़ाइल के लिए foofoo प्रिंट foofoo , पुनरावर्ती रूप से इस व्यवहार का कारण यह है कि शेल द्वारा एक बार पाइप लाइन क्रियान्वित की जाती है, जब यह पूरे कमांड का विस्तार करती है

sed पाइप लाइन को ऐसे तरीके से उद्धृत करने का कोई तरीका नहीं है, जो इसे प्रत्येक फ़ाइल के लिए निष्पादित करेगा, क्योंकि find शेल के माध्यम से कमांड निष्पादित नहीं करता है और पाइपलाइनों या बैकक्वोट्स की कोई धारणा नहीं है। जीएनयू खोज्युटिल मैनुअल बताता है कि एक अलग शेल स्क्रिप्ट में पाइप लाइन डालने से इसी तरह की कार्य कैसे करें:

 #!/bin/sh echo "$1" | sed 's/_test.rb$/_spec.rb/' 

(एक आदेश में यह सब करने के लिए sh -c और एक टन कोट का उपयोग करने के कुछ प्रतिकूल तरीके हो सकते हैं, लेकिन मैं कोशिश नहीं कर रहा हूं।)

इसे मूल समस्या के सबसे करीब के रूप में हल करने के लिए शायद एक्सग्स "आर्ग्स प्रति कमांड लाइन" विकल्प का प्रयोग किया जाएगा:

 find . -name *_test.rb | sed -e "p;s/test/spec/" | xargs -n2 mv 

यह फाइलें मौजूदा कामकाजी डायरेक्टरी में फिर से, मूल फ़ाइल नाम ( p ) को प्रतिध्वनित करती है और फिर एक संशोधित नाम ( s/test/spec/ ) करती है और यह सभी को mv में जोड़ा जाता है ( xargs -n2 )। सावधान रहें कि इस मामले में पथ में स्ट्रिंग test नहीं होना चाहिए।

आप अन्य तरीकों पर विचार करना चाह सकते हैं

 for file in $(find . -name "*_test.rb") do echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/` done 

मुझे यह एक छोटा लगता है

 find . -name '*_test.rb' -exec bash -c 'echo mv $0 ${0/test.rb/spec.rb}' {} \; 

यदि आप चाहते हैं, तो आप इसे बिना बिना कर सकते हैं:

 for i in `find -name '*_test.rb'` ; do mv $i ${i%%_test.rb}_spec.rb ; done 

${var%%suffix} var के मान से suffix स्ट्रिप्स

या, यह प्रयोग करने के लिए sed:

 for i in `find -name '*_test.rb'` ; do mv $i `echo $i | sed 's/test/spec/'` ; done 

आप का उल्लेख करते हैं कि आप अपने शैल के रूप में bash का उपयोग कर रहे हैं, इस स्थिति में आपको वास्तव में बैच का नाम बदलने की ज़रूरत नहीं है और आप इसे पुनः प्राप्त करने की आवश्यकता नहीं है …

मान लें कि आप अपने शैल के रूप में bash का उपयोग कर रहे हैं:

 $ echo $SHELL /bin/bash $ _ 

… और मानते हुए कि आपने तथाकथित globstar शैल विकल्प को सक्षम किया है:

 $ shopt -p globstar shopt -s globstar $ _ 

… और अंत में मान लें कि आपने rename उपयोगिता स्थापित की है ( util-linux-ng पैकेज में पाया गया है)

 $ which rename /usr/bin/rename $ _ 

… तो आप एक-लाइनर में बैच का नाम बदल कर निम्नानुसार प्राप्त कर सकते हैं:

 $ rename _test _spec **/*_test.rb 

( globstar शैल विकल्प यह सुनिश्चित करेगा कि बाश को सभी मिलान *_test.rb फ़ाइलें *_test.rb , चाहे वे निर्देशिका पदानुक्रम में कितनी गहराई से घोंसले हों … help shopt विकल्प को कैसे सेट करें यह पता लगाने के लिए कि विकल्प कैसे सेट करें)

सबसे आसान तरीका :

 find . -name "*_test.rb" | xargs rename s/_test/_spec/ 

सबसे तेज़ तरीका (मान लें कि आपके पास 4 प्रोसेसर हैं):

 find . -name "*_test.rb" | xargs -P 4 rename s/_test/_spec/ 

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

आप getconf ARG_MAX का उपयोग करके अपने सिस्टम की सीमा को getconf ARG_MAX

अधिकांश लिनक्स सिस्टम पर आप free -b उपयोग कर सकते cat /proc/meminfo free -b या cat /proc/meminfo यह जानने के लिए कि आपके साथ कितना रैम काम करना है; अन्यथा, top या आपके सिस्टम गतिविधि मॉनीटर ऐप का उपयोग करें

एक सुरक्षित तरीका (मान लें कि आपके पास काम करने के लिए राम के 1000000 बाइट हैं):

 find . -name "*_test.rb" | xargs -s 1000000 rename s/_test/_spec/ 

यदि आपके पास रूबी (1.9+) है

 ruby -e 'Dir["**/*._test.rb"].each{|x|test(?f,x) and File.rename(x,x.gsub(/_test/,"_spec") ) }' 

रम्पटम के जवाब में जो मुझे पसंद है, खोज का हिस्सा ठीक है लेकिन शेष नहीं है यदि पथ में रिक्त स्थान है। मैं sed से भी परिचित नहीं हूँ, लेकिन मैं इस उत्तर को संशोधित करने में सक्षम था:

 find . -name "*_test.rb" | perl -pe 's/^((.*_)test.rb)$/"\1" "\2spec.rb"/' | xargs -n2 mv 

मुझे इस तरह एक बदलाव की ज़रूरत है क्योंकि मेरे इस्तेमाल के मामले में अंतिम कमांड ज्यादा पसंद करती है

 find . -name "olddir" | perl -pe 's/^((.*)olddir)$/"\1" "\2new directory"/' | xargs -n2 mv 

मुझे फिर से यह करने के लिए दिल नहीं है, लेकिन मैंने यह लिखा सिड एक्सीक को खोजने के लिए उत्तर में लिखा था। वहाँ पूछने वाला एक पूरे पेड़ को स्थानांतरित करने के लिए, संभवतः एक निर्देशिका या दो को छोड़कर, और सभी फाइलों और निर्देशिकाओं का नाम बदलने के लिए "OLD" को "NEW" में स्थानांतरित करना चाहता था

कैसे नीचे श्रमसाध्य शब्दशः के साथ वर्णन करने के अलावा, यह विधि अनूठा भी हो सकती है जिसमें यह अंतर्निहित डीबगिंग शामिल है। यह मूलतः कुछ भी ऐसा नहीं करता है, लिखित रूप में लिखित रूप में लिखित रूप से लिखे गए सभी आदेशों को संकलित और सहेजते हैं, जो मानते हैं कि उसे अनुरोध किया गया काम करने के लिए करना चाहिए।

यह स्पष्ट रूप से जितनी संभव हो लूप को बचाता है। पैटर्न के एक से अधिक मैच के लिए फिर से यादृच्छिक खोज के अलावा, जहां तक ​​मुझे पता है कोई और पुनरावर्ती नहीं है।

और आखिरकार, यह पूरी तरह null सीमांकित है – यह किसी भी फ़ाइल के नाम पर किसी भी नाम की null को छोड़कर यात्रा नहीं करता है। मुझे नहीं लगता कि आपको ये होना चाहिए।

वैसे, यह वास्तव में तेजी से है देखो:

 % _mvnfind() { mv -n "${1}" "${2}" && cd "${2}" > read -r SED <<SED > :;s|${3}\(.*/[^/]*${5}\)|${4}\1|;t;:;s|\(${5}.*\)${3}|\1${4}|;t;s|^[0-9]*[\t]\(mv.*\)${5}|\1|p > SED > find . -name "*${3}*" -printf "%d\tmv %P ${5} %P\000" | > sort -zg | sed -nz ${SED} | read -r ${6} > echo <<EOF > Prepared commands saved in variable: ${6} > To view do: printf ${6} | tr "\000" "\n" > To run do: sh <<EORUN > $(printf ${6} | tr "\000" "\n") > EORUN > EOF > } % rm -rf "${UNNECESSARY:=/any/dirs/you/dont/want/moved}" % time ( _mvnfind ${SRC=./test_tree} ${TGT=./mv_tree} \ > ${OLD=google} ${NEW=replacement_word} ${sed_sep=SsEeDd} \ > ${sh_io:=sh_io} ; printf %b\\000 "${sh_io}" | tr "\000" "\n" \ > | wc - ; echo ${sh_io} | tr "\000" "\n" | tail -n 2 ) <actual process time used:> 0.06s user 0.03s system 106% cpu 0.090 total <output from wc:> Lines Words Bytes 115 362 20691 - <output from tail:> mv .config/replacement_word-chrome-beta/Default/.../googlestars \ .config/replacement_word-chrome-beta/Default/.../replacement_wordstars 

नोट: उपर्युक्त function को sed GNU संस्करणों की आवश्यकता होगी और इसे ठीक से find printf और फिर से sed -z -e को find printf के find printf और :;recursive regex test;t कॉल यदि ये आपके लिए उपलब्ध नहीं हैं, तो कार्यक्षमता को कुछ छोटी समायोजनों के साथ दोहराया जा सकता है।

यह सब कुछ करना चाहिए जो आपको शुरू से ही बहुत कम उपद्रव से पूरा करना था। मैं sed साथ fork था, लेकिन मैं कुछ sed फिर से पढ़ना चाहता हूं, इसलिए मैं यहां हूँ। यह नाई स्कूल में डिस्काउंट बाल कटवाने की तरह है, मुझे लगता है यहां कार्यप्रवाह है:

  • rm -rf ${UNNECESSARY}
    • मैंने जानबूझकर किसी भी कार्यात्मक कॉल को छोड़ दिया है जो किसी भी तरह के डेटा को नष्ट या नष्ट कर सकता है। आप का उल्लेख करते हैं कि ./app अवांछित हो सकता है इसे हटा दें या इसे पहले कहीं और स्थानांतरित करें, या, वैकल्पिक रूप से, आप \( -path PATTERN -exec rm -rf \{\} \) एक \( -path PATTERN -exec rm -rf \{\} \) रुटीन में निर्माण कर सकते find , लेकिन यह एक सब तुम्हारा है
  • _mvnfind "${@}"
    • अपने तर्कों को घोषित करें और कार्यकर्ता कार्य को कॉल करें। ${sh_io} विशेष रूप से महत्वपूर्ण है क्योंकि यह फ़ंक्शन से रिटर्न की बचत करता है। ${sed_sep} एक दूसरे के पास आता है; यह एक मनमाना स्ट्रिंग है जो समारोह में एसएएल के पुनरावर्तन को संदर्भित करता है। यदि ${sed_sep} एक ऐसे मान पर सेट है जो संभावित रूप से आपके किसी भी पथ- या फ़ाइल-नामों में पाया जा सकता है … ठीक है, बस इसे न दें
  • mv -n $1 $2
    • पूरे पेड़ को शुरुआत से स्थानांतरित कर दिया गया है यह बहुत सारे सिरदर्द को बचाएगा; मुझ पर विश्वास करो। आप जो बाकी करना चाहते हैं – फिर से नामकरण – केवल फाइल सिस्टम मेटाडाटा का मामला है यदि आप, उदाहरण के लिए, एक ड्राइव से दूसरे में, या किसी भी प्रकार की फाइल सिस्टम सीमाओं में इसे स्थानांतरित करने के लिए, आप एक आदेश के साथ एक बार ऐसा करने से बेहतर हो यह भी सुरक्षित है नोट -noclobber लिए -noclobber विकल्प सेट; लिखित रूप में, यह फ़ंक्शन ${SRC_DIR} नहीं डालता है, जहां ${TGT_DIR} पहले से मौजूद है।
  • read -R SED <<HEREDOC
    • मैं यहां सभी सीएएल के आदेशों को बाधाओं से बचने के लिए बचाने के लिए और उन्हें नीचे चर के लिए फ़ीड करने के लिए एक चर में पढ़ता हूं। स्पष्टीकरण नीचे
  • find . -name ${OLD} -printf
    • हम find प्रक्रिया शुरू करते find खोज के साथ हम केवल उसी चीज़ के लिए खोजते हैं, जिसको नाम बदलने की जरूरत है क्योंकि हमने फ़ंक्शन की पहली कमांड के साथ पहले से ही सभी जगह mv ऑपरेशन किया था। उदाहरण के लिए, किसी exec कॉल की तरह, किसी भी सीधा कार्रवाई को लेने के बजाय, हम इसके बजाय -printf साथ कमांड लाइन को गतिशील रूप से बनाने के लिए इसका इस्तेमाल करते हैं
  • %dir-depth :tab: 'mv '%path-to-${SRC}' '${sed_sep}'%path-again :null delimiter:'
    • find बाद फ़ाइलों को find बाद हमें इसकी आवश्यकता होती है कि वह सीधे कमांड के निर्माण और प्रिंट करता है ( अधिकतर ) हमें आपके नाम बदलने पर कार्रवाई करने की ज़रूरत होगी। प्रत्येक पंक्ति की शुरुआत में हमले की %dir-depth से यह सुनिश्चित करने में मदद मिलेगी कि हम किसी ऐसे मूल ऑब्जेक्ट के साथ पेड़ में फ़ाइल या निर्देशिका का नाम बदलने का प्रयास नहीं कर रहे हैं, जिसका अभी नाम बदला गया है। आपके फाइलसिस्टम ट्री पर चलने के लिए सभी प्रकार के अनुकूलन तकनीकों का उपयोग करता है और यह एक निश्चित बात नहीं है कि यह एक सुरक्षित-ऑर्डर-ऑपरेशन ऑर्डर में आवश्यक डेटा वापस करेगा। यही कारण है कि हम अगले …
  • sort -general-numerical -zero-delimited
    • हम %directory-depth आधार पर सभी आउटपुट के आउटपुट को सॉर्ट करते find ताकि $ {SRC} के संबंध में निकटतम पथ पहले काम किए जाएंगे। यह गैर-मौजूद स्थानों में mv फाइलों को शामिल करने में संभावित त्रुटियों से बचा जाता है, और यह रिकर्सिव पाशन के लिए की आवश्यकता को कम करता है। ( वास्तव में, आप सभी को एक पाश खोजने के लिए कड़ी मेहनत कर सकते हैं )
  • sed -ex :rcrs;srch|(save${sep}*til)${OLD}|\saved${SUBSTNEW}|;til ${OLD=0}
    • मुझे लगता है कि यह पूरी स्क्रिप्ट में एकमात्र पाश है, और यह प्रत्येक स्ट्रिंग के लिए दूसरी %Path मुद्रित की गई है, अगर इसमें एक से अधिक $ {OLD} मान की आवश्यकता हो सकती है जो कि जगह की आवश्यकता हो सकती है। मैंने सोचा अन्य सभी समाधान एक दूसरे sed प्रक्रिया शामिल हैं, और एक छोटी लूप वांछनीय नहीं हो सकती है, निश्चित रूप से यह स्पॉलिंग को धड़क रहा है और पूरी प्रक्रिया को फंसती है
    • तो मूल रूप से sed यहां $ {sed_sep} की तलाश में है, तब इसे मिला है, इसे सहेजता है और सभी वर्णों का मिलान तब तक हो जाता है जब तक कि यह $ $ {OLD} न मिल जाए, जो इसके बाद $ $ {NEW} के साथ बदलता है। यह तब वापस $ {sed_sep} पर वापस आती है और $ {OLD} के लिए फिर से दिखता है, अगर यह स्ट्रिंग में एक से अधिक बार होता है यदि यह नहीं मिला है, तो यह संशोधित स्ट्रिंग को stdout प्रिंट करता है (जो इसे फिर से कैद करता है) और लूप समाप्त हो जाता है।
    • यह पूरे स्ट्रिंग को पार्स करने से बचा जाता है, और यह सुनिश्चित करता है कि mv कमांड स्ट्रिंग के पहले भाग में, जिसमें $ {OLD} को शामिल करना आवश्यक है, इसमें शामिल है, और दूसरी छमाही को कई बार बदल दिया जाता है जैसे कि पोंछना आवश्यक है mv के गंतव्य पथ से $ {OLD} नाम
  • sed -ex...-ex search|%dir_depth(save*)${sed_sep}|(only_saved)|out
    • यहां दो- -exec कॉल्स दूसरी fork बिना होते हैं। पहले, जैसा कि हमने देखा है, हम $ {OLD} से $ $ {NEW} के सभी संदर्भों को ठीक से बदलने के लिए आवश्यक के रूप में खोज -printf फ़ंक्शन कमांड द्वारा प्रदान की गई mv कमांड को संशोधित करते हैं, लेकिन ऐसा करने के लिए कुछ मनमानी संदर्भ बिंदुओं का उपयोग करना था जिन्हें अंतिम आउटपुट में शामिल नहीं किया जाना चाहिए। इसलिए एक बार जब यह सब करने की जरूरत होती है, तो हम उसे इसे पास करने से पहले पकड़-बफर से अपने संदर्भ बिंदुओं को समाप्त करने के लिए निर्देश देते हैं।

और अब हम आस पास हैं

read वाले एक ऐसा आदेश प्राप्त होगा जो इस तरह दिखता है:

 % mv /path2/$SRC/$OLD_DIR/$OLD_FILE /same/path_w/$NEW_DIR/$NEW_FILE \000 

इसे इसे ${msg} में ${sh_io} रूप में ${sh_io} जाएगा जो फ़ंक्शन के बाहर की इच्छा के ${sh_io} जांच की जा सकती है।

ठंडा।

-माइक

मैं ओटैक द्वारा सुझाए गए उदाहरणों का पालन ​​करके रिक्त स्थान के साथ फ़ाइल नामों को संभालना सक्षम था

यह नहीं तोड़ता है यदि पथ में रिक्त स्थान या स्ट्रिंग test :

 find . -name "*_test.rb" -print0 | while read -d $'\0' file do echo mv "$file" "$(echo $file | sed s/test/spec/)" done 

यह एक उदाहरण है जो सभी मामलों में काम करना चाहिए। रिकर्सिवले का निर्माण करता है, केवल शेल की आवश्यकता है, और रिक्त स्थान के साथ नामों का समर्थन करता है।

 find spec -name "*_test.rb" -print0 | while read -d $'\0' file; do mv "$file" "`echo $file | sed s/test/spec/`"; done 
 $ find spec -name "*_test.rb" spec/dir2/a_test.rb spec/dir1/a_test.rb $ find spec -name "*_test.rb" | xargs -n 1 /usr/bin/perl -e '($new=$ARGV[0]) =~ s/test/spec/; system(qq(mv),qq(-v), $ARGV[0], $new);' `spec/dir2/a_test.rb' -> `spec/dir2/a_spec.rb' `spec/dir1/a_test.rb' -> `spec/dir1/a_spec.rb' $ find spec -name "*_spec.rb" spec/dir2/b_spec.rb spec/dir2/a_spec.rb spec/dir1/a_spec.rb spec/dir1/c_spec.rb 

आपके सवाल के बारे में sed लगता है, लेकिन पुनरावर्ती नाम बदलने के अपने लक्ष्य को पूरा करने के लिए, मैं निम्नलिखित का सुझाव देता हूं, मैं यहां दिए गए एक और उत्तर से बेतरतीब ढंग से फट गया हूं: पुनरावर्ती नाम का नाम बदलें

 #!/bin/bash IFS=$'\n' function RecurseDirs { for f in "$@" do newf=echo "${f}" | sed -e 's/^(.*_)test.rb$/\1spec.rb/g' echo "${f}" "${newf}" mv "${f}" "${newf}" f="${newf}" if [[ -d "${f}" ]]; then cd "${f}" RecurseDirs $(ls -1 ".") fi done cd .. } RecurseDirs . 

खोजने के उपयोग के साथ नाम बदलने का और अधिक सुरक्षित तरीका और नियमित अभिव्यक्ति प्रकार:

  mkdir ~/practice cd ~/practice touch classic.txt.txt touch folk.txt.txt 

".txt.txt" एक्सटेंशन को निम्नानुसार निकालें –

  cd ~/practice find . -name "*txt" -execdir sh -c 'mv "$0" `echo "$0" | sed -r 's/\.[[:alnum:]]+\.[[:alnum:]]+$//'`' {} \; 

यदि आप के स्थान पर + का उपयोग करते हैं; बैच मोड पर काम करने के लिए, उपरोक्त कमांड केवल पहली मिलान फ़ाइल का नाम बदल लेगा, लेकिन फ़ाइल की पूरी सूची 'खोज' से मेल नहीं करेगी

  find . -name "*txt" -execdir sh -c 'mv "$0" `echo "$0" | sed -r 's/\.[[:alnum:]]+\.[[:alnum:]]+$//'`' {} + 

यहाँ एक अच्छा यात्री है जो चाल करता है सेड इस अधिकार को संभाल नहीं सकते हैं, खासकर यदि कई चर को xarg से -n 2 के साथ पारित किया जाता है। एक बैश प्रतिस्थापन आसानी से इसे संभालता है:

 find ./spec -type f -name "*_test.rb" -print0 | xargs -0 -I {} sh -c 'export file={}; mv $file ${file/_test.rb/_spec.rb}' 

जोड़ना -प्रकार -एफ स्थानांतरित करने के लिए केवल फाइलों को सीमित करेगा, -प्रचार 0 पथ में रिक्त स्थान को संभाल देगा।

यहां मेरे लिए क्या काम किया जब फाइल नामों में उनके स्थान थे। नीचे दिए गए उदाहरण .zip फ़ाइलों के लिए सभी .dar फ़ाइलों को पुनः नामित करता है:

 find . -name "*.dar" -exec bash -c 'mv "$0" "`echo \"$0\" | sed s/.dar/.zip/`"' {} \; 

इसके लिए आपको sed की ज़रूरत नहीं है। प्रक्रिया पूर्ण प्रतिस्थापन के माध्यम से find के परिणामस्वरूप आप पूरी तरह से अकेले पा सकते हैं।

इसलिए यदि आपके पास एक find अभिव्यक्ति है जो आवश्यक फ़ाइलों का चयन करती है, तो सिंटैक्स का उपयोग करें:

 while IFS= read -r file; do echo "mv $file ${file%_test.rb}_spec.rb" # remove "echo" when OK! done < <(find -name "*_test.rb") 

यह फाइलों को find लेगा और उन सभी को पुनः नामित करेगा जो स्ट्रिंग _test.rb को अंत से _test.rb और _spec.rb को _test.rb

इस चरण के लिए हम शैल पैरामीटर विस्तार का उपयोग करते हैं जहां ${var%string} $var से कम से कम मिलान पैटर्न "स्ट्रिंग" निकाल देता है

 $ file="HELLOa_test.rbBYE_test.rb" $ echo "${file%_test.rb}" # remove _test.rb from the end HELLOa_test.rbBYE $ echo "${file%_test.rb}_spec.rb" # remove _test.rb and append _spec.rb HELLOa_test.rbBYE_spec.rb 

एक उदाहरण देखें:

 $ tree . ├── ab_testArb ├── a_test.rb ├── a_test.rb_test.rb ├── b_test.rb ├── c_test.hello ├── c_test.rb └── mydir └── d_test.rb $ while IFS= read -r file; do echo "mv $file ${file/_test.rb/_spec.rb}"; done < <(find -name "*_test.rb") mv ./b_test.rb ./b_spec.rb mv ./mydir/d_test.rb ./mydir/d_spec.rb mv ./a_test.rb ./a_spec.rb mv ./c_test.rb ./c_spec.rb