शेल स्क्रिप्ट का उपयोग करके लिनक्स में अंडरस्कोर के साथ सभी फ़ाइल नामों में रिक्त स्थान कैसे बदलें?


17

मैंने शेल स्क्रिप्ट का अनुसरण करने की कोशिश की, जिसे सभी xml फ़ाइलनाम से रिक्त स्थान बदलना चाहिए

for xml_file in $(find $1 -name "* .xml" -type f);
do
 echo "removing spaces from XML file:" $xml_file
 mv "$xml_file" "${xml_file// /_}";
done

मान लीजिए, मेरे पास नाम के साथ xml फ़ाइल है xy z.xml, तो यह देता है:

removing spaces from XML file: /home/krishna/test/xy
mv: cannot stat `/home/krishna/test/xy': No such file or directory
removing spaces from XML file: .xml
mv: cannot stat `z.xml': No such file or directory

जवाबों:


29

इसके साथ इसका प्रयोग करें bash:

find $1 -name "* *.xml" -type f -print0 | \
  while read -d $'\0' f; do mv -v "$f" "${f// /_}"; done

findनाम में एक जगह के साथ फ़ाइलों के लिए खोज करेंगे। फाइलनामों को एक नलबीट ( -print0) के रूप में मुद्रित किया जाएगा जो विशेष फिल्टनाम के साथ सामना करने के लिए सीमांकक के रूप में होगा। तब readबिलिन नलिन द्वारा सीमांकित फाइलनाम पढ़ता है और अंत में mvएक अंडरस्कोर के साथ रिक्त स्थान को बदल देता है।

संपादित करें: यदि आप निर्देशिकाओं में रिक्त स्थान भी निकालना चाहते हैं, तो यह थोड़ा अधिक जटिल है। निर्देशिकाओं का नाम बदल दिया जाता है और फिर नाम से सुलभ नहीं होता findहै। इसे इस्तेमाल करे:

find -name "* *" -print0 | sort -rz | \
  while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done

sort -rzफ़ाइल क्रम उलट जाता है, तो यह है कि एक फ़ोल्डर में गहरी फ़ाइलें पहले स्थानांतरित करने के लिए और फ़ोल्डर को स्वयं पिछले एक हो जाएगा रहे हैं। इसलिए, सभी फ़ाइलों और फ़ोल्डर का नाम बदलकर उसके अंदर नाम बदलने से पहले कभी भी फ़ोल्डर का नाम नहीं लिया जाता है। mvपाश में आदेश एक सा भी बदल रहा है। लक्ष्य नाम में, हम केवल फ़ाइल के बेसनेम में रिक्त स्थान हटाते हैं, अन्यथा यह सुलभ नहीं होगा।


मैं सभी निर्देशिका में अंडरस्कोर के साथ रिक्त स्थान को बदलने की कोशिश कर रहा हूं, लेकिन यह त्रुटि दे रहा है क्योंकि नाम बदलने के बाद वह निर्देशिका सुलभ नहीं है।
krishna

@krishna मैंने अपने उत्तर में एक संपादन जोड़ा।
अराजकता

1
@ वोस वाह, बस इन दो को दो सिस्टम पर चलाया और यह एक आकर्षण की तरह काम किया, कुछ फाइलें और डायर नहीं गुजर रहा है लेकिन यह केवल कुछ है
कुछ भी नहीं

MacOS पर हमें thename विकल्प से पहले डायरेक्टरी को डायरेक्टरी में निर्दिष्ट करना होगा find . -name "* *" -print0 | sort -rz | \ while read -d $'\0' f; do mv -v "$f" "$(dirname "$f")/$(basename "${f// /_}")"; done
Laszlo Pinter

17
  1. का उपयोग करते हुए rename

    find . -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;

    या के साथ $1

    find "$1" -type f -name "* *.xml" -exec rename "s/\s/_/g" {} \;
  2. का उपयोग करते हुए mv

    find . -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;

    या के साथ $1

    find "$1" -type f -name "* *.xml" -exec bash -c 'mv "$0" "${0// /_}"' {} \;

मुझे नहीं पता, लेकिन आपके दिए गए आदेश मेरे लिए काम नहीं कर रहे हैं। यह कोई त्रुटि और आउटपुट नहीं दिखा रहा है।
krishna

@कृष्ण ने सही किया, क्षमा करें
AB

1
नाम बदलकर मेरे लिए काम किया। पहली टक्कर!
ब्रायन पियरसी

1

यह एक ऐसी विधि है जिसे मैंने उसी समस्या का सामना करते हुए पाया:

for f in *; do mv "$f" `echo $f | tr ' ' '_'`; done

मैं अपने ssl प्रमाणपत्र को स्वचालित रूप से अद्यतन करने के लिए एक bash स्क्रिप्ट फ़ाइल लिख रहा था।


1

उपयोग करें rename:

rename 's/\s/_/g' ./*.xml

कोई ज़रूरत नहीं है find:)


1
रेगेक्स में ट्रेलिंग जी जोड़ें और यह पूरी तरह से काम करता है। 's / \ s / _ / g'
जंभाई

अच्छी टिप, धन्यवाद :)
Jan Werkhoven
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.