2011-01-09 11 views
5

मैं उपयोग कर रहा हूँ एक के लिए लूप इस एक के लिए इसी तरह 16 वर्णों के लिए एक फ़ोल्डर में सभी फ़ाइल नाम काटना:बैश: छोटा करें फ़ाइल नाम, उन्हें अद्वितीय रखने

for i in *; do 
    Shortname=${i:0:16}  # Let's assume I don't need the extension 
    mv "$i" "$Shortname" 
done 

समस्या है: जब भी दो फ़ाइल नाम है पहले 16 अक्षर, बाद वाला एक पिछले एक को ओवरराइट करेगा (ओएस एक्स एमवी उस तरह से व्यवहार करता है)।

मैं कैसे जांच सकता हूं कि "शॉर्टनाम" नाम वाली फ़ाइल पहले से मौजूद है या नहीं, और यदि ऐसा है, तो किसी संख्या के साथ "शॉर्टनाम" के अंतिम वर्ण को प्रतिस्थापित करें। फिर फिर से जांचें कि उस नाम वाली फ़ाइल मौजूद है, और यदि ऐसा है, तो उच्च संख्या आज़माएं। और इसी तरह। यदि यह संख्या 9 पर आता है और अब तक सभी नामों को लिया गया है, तो इसे "शॉर्टनाम" के अंतिम TWO वर्णों को "10" के साथ प्रतिस्थापित करना चाहिए और जांचें कि वह फ़ाइल पहले से मौजूद है या नहीं।

उदाहरण: मान लें कि मैं इसे में निम्न फ़ाइलों के साथ एक निर्देशिका करते हैं:

MyTerriblyLongLongFirstFile.jpg 
MyTerriblyLongLongSecondFile.jpg 
MyTerriblyLongLongThirdFile.jpg 
... 
MyTerriblyLongLongFourteenthFile.jpg 
... 
MyTerriblyLongLongOneHundredSixtySeventhFile.jpg 
... 
MyTerriblyLongLongFiveMillionthFile.jpg 

ध्यान दें कि पहले 16 पत्र सभी फ़ाइलों के लिए ही हैं। स्क्रिप्ट चलाने के बाद, मैं चाहते हैं उन्हें यह करने के लिए नाम बदलने की:

MyTerriblyLongL1.jpg 
MyTerriblyLongL2.jpg 
MyTerriblyLongL3.jpg 
... 
MyTerriblyLong14.jpg 
... 
MyTerriblyLon167.jpg 
... 
MyTerribl5000000.jpg 

इससे कोई फर्क नहीं पड़ता अगर "MyTerriblyLongLongFourteenthFile.jpg" "MyTerriblyLong14.jpg", कि वर्णमाला छंटाई पर निर्भर करता है के लिए नाम दिया गया है। यह सिर्फ इतना महत्वपूर्ण है कि उनमें से प्रत्येक को एक अद्वितीय नाम मिलता है।

ऐसा करने का सबसे अच्छा तरीका क्या है?

उत्तर

4

पहले परीक्षण फ़ाइलों पर इसे आजमाएं। mv के बजाय echo का उपयोग कर परीक्षण की सामान्य विधि आपको संभावित नाम टकराव नहीं बनाए जाने के बाद से बहुत कुछ नहीं बताएगी।

#!/bin/bash 
num=1 
length=16 
for file in M*.jpg 
do 
    newname=$file 
    until [[ ! -f $newname ]] 
    do 
     ((sublen = length - ${#num})) 
     printf -v newname '%.*s%d' "$sublen" "$file" "$num" 
     ((num++)) 
    done 
    mv "$file" "$newname" 
done 

परीक्षण:

$ touch MyTerriblyLongLongFilenames{a..k}.jpg 
$ touch MyTerriblyLongL3 
$ ls M* 
MyTerriblyLongL3     MyTerriblyLongLongFilenamesf.jpg 
MyTerriblyLongLongFilenamesa.jpg MyTerriblyLongLongFilenamesg.jpg 
MyTerriblyLongLongFilenamesb.jpg MyTerriblyLongLongFilenamesh.jpg 
MyTerriblyLongLongFilenamesc.jpg MyTerriblyLongLongFilenamesi.jpg 
MyTerriblyLongLongFilenamesd.jpg MyTerriblyLongLongFilenamesj.jpg 
MyTerriblyLongLongFilenamese.jpg MyTerriblyLongLongFilenamesk.jpg 
$ ./nocollide 
$ ls M* 
MyTerriblyLong10 MyTerriblyLongL1 MyTerriblyLongL4 MyTerriblyLongL7 
MyTerriblyLong11 MyTerriblyLongL2 MyTerriblyLongL5 MyTerriblyLongL8 
MyTerriblyLong12 MyTerriblyLongL3 MyTerriblyLongL6 MyTerriblyLongL9 
+0

आप आदमी कर रहे हैं। आपका बहुत बहुत धन्यवाद! – Martin