जवाबों:
एक पोर्टेबल तरीका (जो किसी भी POSIX आज्ञाकारी प्रणाली पर काम करेगा):
find /the/path -depth -name "*.abc" -exec sh -c 'mv "$1" "${1%.abc}.edefg"' _ {} \;
Bash4 में, आप पुनरावर्ती ग्लब्स (**) प्राप्त करने के लिए ग्लोबस्टार का उपयोग कर सकते हैं:
shopt -s globstar
for file in /the/path/**/*.abc; do
mv "$file" "${file%.abc}.edefg"
done
rename
उबंटू में (पर्ल) कमांड पर्ल रेगुलर एक्सप्रेशन सिंटैक्स का उपयोग करके फ़ाइलों का नाम बदल सकती है, जिसे आप ग्लोबस्टार या के साथ जोड़ सकते हैं find
:
# Using globstar
shopt -s globstar
files=(/the/path/**/*.abc)
# Best to process the files in chunks to avoid exceeding the maximum argument
# length. 100 at a time is probably good enough.
# See http://mywiki.wooledge.org/BashFAQ/095
for ((i = 0; i < ${#files[@]}; i += 100)); do
rename 's/\.abc$/.edefg/' "${files[@]:i:100}"
done
# Using find:
find /the/path -depth -name "*.abc" -exec rename 's/\.abc$/.edefg/' {} +
इसके अलावा http://mywiki.wooledge.org/BashFAQ/030 देखें
${1%.abc}...
sh -c
पहले तर्क के साथ $ 0 को सौंपा गया है और किसी भी शेष तर्क को स्थितीय मापदंडों को सौंपा गया है । तो _
यह एक डमी तर्क है, और '{}' पहला पद है sh -c
।
यह आवश्यक कार्य करेगा यदि सभी फाइलें एक ही फ़ोल्डर में हैं
rename 's/.abc$/.edefg/' *.abc
फ़ाइलों का नाम बदलने के लिए इसे पुन: उपयोग करें:
find /path/to/root/folder -type f -name '*.abc' -print0 | xargs -0 rename 's/.abc$/.edefg/'
rename 's/.abc$/.edefg/' /path/to/root/folder/**/*.abc
बैश के आधुनिक संस्करण में।
s
शुरुआत में क्या है, और मैं अन्य विकल्पों का क्या उपयोग कर सकता हूं। धन्यवाद !
पुनरावर्ती नाम बदलने के साथ एक समस्या यह है कि आप फ़ाइलों का पता लगाने के लिए जो भी विधि का उपयोग करते हैं, वह rename
केवल फ़ाइल नाम के लिए नहीं बल्कि पूरे रास्ते से गुजरती है । यह नेस्टेड फ़ोल्डर्स में जटिल नाम बदलने के लिए कठिन बनाता है।
मैं उपयोग find
की -execdir
इस समस्या को हल करने के लिए कार्रवाई की। यदि आप -execdir
इसके बजाय उपयोग करते हैं -exec
, तो निर्दिष्ट कमांड उपनिर्देशिका से मेल खाते फ़ाइल से चलाया जाता है। इसलिए, पूरे रास्ते को पारित करने के बजाय rename
, यह केवल गुजरता है ./filename
। इससे रेगेक्स लिखना बहुत आसान हो जाता है।
find /the/path -type f \
-name '*.abc' \
-execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;
विस्तार से:
-type f
इसका मतलब केवल फाइलों को देखना है, निर्देशिकाओं को नहीं-name '*.abc'
का मतलब केवल उन फिल्नामों से है जो अंत में .abc से मेल खाते हैं'{}'
वह प्लेसहोल्डर है जो उस जगह को चिह्नित करता है जहां -execdir
पाया गया पथ सम्मिलित होगा। सिंगल-कोट्स की आवश्यकता होती है, यह रिक्त स्थान और शेल वर्णों के साथ फ़ाइल नामों को संभालने की अनुमति देता है।-type
और -name
बैश लाइन-निरंतरता चरित्र हैं। मैं उन्हें इस उदाहरण को और अधिक पठनीय बनाने के लिए उपयोग करता हूं, लेकिन यदि आप अपनी आज्ञा को एक पंक्ति में रखते हैं, तो उनकी आवश्यकता नहीं है।-execdir
पंक्ति के अंत में बैकस्लैश आवश्यक है। यह अर्धविराम से बचने के लिए है, जो इसके द्वारा संचालित कमांड को समाप्त करता है -execdir
। आनंद!रेगेक्स की व्याख्या:
s/
रेगेक्स की शुरुआत\.\/
अग्रणी से मिलाएं। /। -से बचने के लिए उपयोग करें। और / मेटाचैटर्स (ध्यान दें: यह हिस्सा आपके संस्करण के आधार पर भिन्न होता है find
। उपयोगकर्ता @apollo की टिप्पणी देखें)(.+)
फ़ाइल नाम से मिलान करें। कोष्ठक बाद में उपयोग के लिए मैच पर कब्जा कर लेते हैं\.abc
डॉट से बचो, एबीसी से मेल करो$
स्ट्रिंग के अंत में मैच को एंकर करें
/
रेगेक्स के "मैच" भाग के अंत को चिह्नित करता है, और "बदलें" भाग की शुरुआत
version1_
इस पाठ को हर फ़ाइल नाम में जोड़ें
$1
मौजूदा फ़ाइल नाम का संदर्भ देता है, क्योंकि हमने इसे कोष्ठक के साथ कैप्चर किया है। यदि आप "मैच" भाग में कोष्ठक के कई सेटों का उपयोग करते हैं, तो आप $ 2, $ 3, आदि का उपयोग करके उन्हें यहां संदर्भित कर सकते हैं।.abc
नया फ़ाइल नाम .abc में समाप्त होगा। "बदलें" अनुभाग में यहां डॉट मेटाचैकर से बचने की आवश्यकता नहीं है/
रेगेक्स का अंतइससे पहले
tree --charset=ascii
|-- a_file.abc
|-- Another.abc
|-- Not_this.def
`-- dir1
`-- nested_file.abc
उपरांत
tree --charset=ascii
|-- version1_a_file.abc
|-- version1_Another.abc
|-- Not_this.def
`-- dir1
`-- version1_nested_file.abc
संकेत: rename
's -n विकल्प उपयोगी है। यह एक सूखा रन करता है और आपको दिखाता है कि यह किस नाम से बदल जाएगा, लेकिन कोई बदलाव नहीं करता है।
--execdir
अग्रणी में पास नहीं हुआ ./
ताकि \.\/
रेगेक्स में भाग छोड़ा जा सके। ऐसा इसलिए हो सकता है क्योंकि मैं OSX पर हूं ubuntu नहीं
एक और पोर्टेबल तरीका:
find /the/path -depth -type f -name "*.abc" -exec sh -c 'mv -- "$1" "$(dirname "$1")/$(basename "$1" .abc).edefg"' _ '{}' \;
# Rename all *.txt to *.text
for f in *.txt; do
mv -- "$f" "${f%.txt}.text"
done
यह भी देखें कि आपको पार्स क्यों नहीं करना चाहिए ls
।
संपादित करें: यदि आपको बेसनेम का उपयोग करना है तो आपका सिंटैक्स होगा:
for f in *.txt; do
mv -- "$f" "$(basename "$f" .txt).text"
done
https://unix.stackexchange.com/questions/19654/changing-extension-to-multiple-files
यह वही है जो मैंने किया और जैसा मैंने चाहा वैसे ही बहुत काम किया। मैंने mv
कमांड का उपयोग किया । मेरे पास कई .3gp
फाइलें थीं और मैं उन सभी का नाम बदलना चाहता था.mp4
यहाँ इसके लिए एक छोटा oneliner है:
for i in *.3gp; do mv -- "$i" "ren-$i.mp4"; done
जो केवल वर्तमान निर्देशिका के माध्यम से स्कैन करता है, सभी .3gp फ़ाइलों को चुनता है, फिर नाम बदलकर (mv का उपयोग करके) करता है ren-name_of_file.mp4
file.3gp
दिया जाएगा file.3gp.mp4
, जो कि ज्यादातर लोग नहीं चाहते हैं।
.3gp
या .mp4
यहाँ सिर्फ समझाने के उद्देश्य से कर रहे थे।
basename "$i" .mp4
"ren- $ i.mp4" के बजाय पिछले एक्सटेंशन को हटाने के लिए उपयोग करूंगा।
मुझे इसे हासिल करने का एक आसान तरीका मिला। Jpg से पीडीएफ में कई फाइलों के एक्सटेंशन बदलने के लिए, उपयोग करें:
for file in /path/to; do mv $file $(basename -s jpg $file)pdf ; done
फ़ाइलों और निर्देशिकाओं का नाम बदलें find -execdir | rename
यदि आप केवल एक प्रत्यय के साथ फाइल और निर्देशिका दोनों का नाम नहीं बदलने जा रहे हैं, तो यह एक अच्छा पैटर्न है:
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find . -depth -execdir rename 's/findme/replaceme/' '{}' \;
इसके विपरीत, कमांड निष्पादित करने से पहले कमाल का -execdir
विकल्प cd
डायरेक्टरी में होता है ।rename
-exec
-depth
यह सुनिश्चित करना कि बच्चों का नामकरण पहले माता-पिता और फिर माता-पिता पर होता है, ताकि लापता माता-पिता की अनुपस्थिति के साथ संभावित समस्याओं को रोका जा सके।
-execdir
आवश्यक है क्योंकि नाम गैर-बेसन इनपुट पथों के साथ अच्छी तरह से नहीं चलता है, उदाहरण के लिए निम्न विफल रहता है:
rename 's/findme/replaceme/g' acc/acc
PATH
हैकिंग की आवश्यकता है क्योंकि है -execdir
एक बहुत कष्टप्रद दोष यह है: find
अत्यंत स्वच्छंद जाता है और साथ कुछ भी करने से मना -execdir
करता है, तो आप अपने किसी भी संबंधित पथ है PATH
वातावरण चर, जैसे ./node_modules/.bin
, साथ में नाकाम रहने के:
खोज: सापेक्ष पथ './node_modules/.bin' को PATH पर्यावरण चर में शामिल किया गया है, जो खोज की -execdir कार्रवाई के साथ संयोजन में असुरक्षित है। कृपया उस प्रविष्टि को $ PATH से हटा दें
यह भी देखें: '-execdir' कार्रवाई का उपयोग उस निर्देशिका के लिए असुरक्षित क्यों है जो PATH में है?
-execdir
एक GNU POSIX के लिए एक्सटेंशन ढूंढता है । rename
पर्ल आधारित है और rename
पैकेज से आता है । उबंटू 18.10 में परीक्षण किया गया।
नाम बदलें समाधान देखें
यदि आपके इनपुट पथ से नहीं आते हैं find
, या यदि आपके पास सापेक्ष पथ झुंझलाहट है, तो हम कुछ पर्ल लुकहेड का उपयोग सुरक्षित रूप से निर्देशिकाओं का नाम बदलने के लिए कर सकते हैं:
git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'
मैं के लिए एक सुविधाजनक अनुरूप नहीं मिला है -execdir
साथ xargs
: https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686
यह sort -r
सुनिश्चित करने के लिए आवश्यक है कि फाइलें उनके संबंधित निर्देशिकाओं के बाद आती हैं, क्योंकि लंबे समय तक पथ एक ही उपसर्ग के साथ छोटे के बाद आते हैं।