Synology-Forum.nl
Firmware => Synology DSM 5.1 en eerder => Topic gestart door: zakhooi op 20 januari 2015, 15:51:56
-
Hoi,
Ik ben op zoek naar een rename script.
Ik weet dat dit al besproken is, maar dat was i.h.k.v. NZB downloads.
Wat ik zoek is anders, ik wil:
- vanaf een bepaalt punt recursief karakters in bestandsnamen veranderen
- waarbij ik zelf aan kan geven welke kakarters ik met welke karakters wil vervangen.
Onder 'normaal' linux gebruik ik daarvoor het rename commando waarmee ik spaties vervang door underscores en dergelijke maar dat commando zit niet in busybox.
Als workaround zou ik de betreffende directory via SMB remote kunnen mounten aan een linux bak en dan alnog mijn script gebruiken, maar ik wil dit binnen de NAS zelf oplossen (mag via commandline).
Weet iemand hier een oplossing voor?
BVD
-
Ik kan je wel helpen aan een klein python scriptje die dit voor je doet.
import os
def replace_all(text, dic):
for i, j in dic.iteritems():
text = text.replace(i, j)
return text
###########
# Main Program #
###########
path = '//NAS/sync/TvSeries'
replacedict = {' ' : '_','originaltekst2' : 'Replacedby2','originaltekst3' : 'Replacedby3' }
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
newfilespecs = dirpath + '/' + replace_all(filename,replacedict)
oldfilespecs = dirpath + '/' + filename
if newfilespecs != oldfilespecs :
#os.rename(oldfilespecs, newfilespecs)
print oldfilespecs + ' --> ' + newfilespecs
else:
print oldfilespecs +' --> Not renamed'
Je moet dan even het path aanpassen aan je eigen wensen en ook de replacedict.
Daar zet je strings paren in die vervangen moeten worden.
Ik heb de echte rename regel even van een kommentaar karaakter voorzien (het #) dan kun je eerst uittesten of alles wel goed gaat voor je hem echt laat renamen.
PS uiteraard moet je wel python geinstalleerd hebben en het script met python aanroepen.
-
Dat is een mooi begin, bedankt!
Ik ben er nu naar aan het kijken. Ik ben bash gewend en doe niets met python dus heb nog wel een paar vragen.
- In replacedict hoe vervang ik een "'" met niets? dan krijg je 3x "'" achter elkaar (''') en dat snapt python niet.
- En wat is 'niets'? Kan ik dan gewoon 2x "'" achter elkaar gebruiken ('')?
- Zijn er ook karakters die geescaped moeten worden of hoeft dat niet onder python?
Met rename verander ik de volgende karakters (daar zoek ik nu dus een python equivalent voor):
rename "s/\(/\[/g" */*
rename "s/\)/\]/g" */*
rename "s/\ /_/g" */*
rename "s/\'//g" */*
rename "s/\&//g" */*
rename "s/\$//g" */*
rename "s/\@//g" */*
rename "s/\!//g" */*
rename "s/\`//g" */*
rename "s/\~//g" */*
rename "s/\+//g" */*
rename "s/\,//g" */*
-
Hier de regel die je kunt opnemen als replacedict.
Het mag ook gewoon op een regel, maar voor het overzicht heb ik de karakters even recht onder elkaar gezet.
En het vervangen met niets doe je achter de dubbele punt twee hoge quotes met niets ertussen op te nemen.
replacedict = {'(' : '[',
')' : ']',
' ' : '_',
'\'' : '',
'&' : '',
'$' : '',
'@' : '',
'!' : '',
'`' : '',
'~' : '',
'+' : '',
',' : '',}
Je kunt die hoge quote toevoegen door er het escape karakter (de \) ervoor te zetten of die hoge quote tussen dubbele quotes te zetten. Dus ofwel '\'' ofwel "'" .
-
Ok hij doet het al best aardig.
Hij neemt alleen de directories zelf niet mee in het renamen.
Is dat een eenvoudige aanpassing? Hoe zou het script er dan uit zien?
-
Ja gewoon nog een for loop op nemen die door de directories loopt zoals hieronder.
for dirpath, dirnames, filenames in os.walk(path):
for dirname in dirnames:
newdirspecs = dirpath + '/' + replace_all(dirname,replacedict)
olddirspecs = dirpath + '/' + dirname
if newdirspecs != olddirspecs :
os.rename(olddirspecs, newdirspecs)
print olddirspecs + ' --> ' + newfilespecs
else:
print olddirspecs +' --> Not renamed'
for filename in filenames:
newfilespecs = dirpath + '/' + replace_all(filename,replacedict)
oldfilespecs = dirpath + '/' + filename
if newfilespecs != oldfilespecs :
#os.rename(oldfilespecs, newfilespecs)
print oldfilespecs + ' --> ' + newfilespecs
else:
print oldfilespecs +' --> Not renamed'
PS wel even testen hoor, want ik schrijf dit uit m'n hoofd zonder het uit te testen.
-
Je had er nog 1 foutje inzitten (newfilespecs ipv newdirspecs), maar nadat ik die eruit heb gehaald werkt het renamen van directories nog niet. Het script draait en genereert output maar in de nieuwe naam staat nog de ongewijzigde naam.
het script ziet er nu zo uit (daadwerkelijk renamen nog uitgehashed).
import os
def replace_all(text, dic):
for i, j in dic.iteritems():
text = text.replace(i, j)
return text
###########
# Main Program #
###########
path = '.'
replacedict = {'(' : '[',
')' : ']',
' ' : '_',
'\'' : '',
'&' : '',
'$' : '',
'@' : '',
'!' : '',
'`' : '',
'~' : '',
'+' : '',
',' : '',}
for dirpath, dirnames, filenames in os.walk(path):
for dirname in dirnames:
newdirspecs = dirpath + '/' + replace_all(dirname,replacedict)
olddirspecs = dirpath + '/' + dirname
if newdirspecs != olddirspecs :
#os.rename(olddirspecs, newdirspecs)
print olddirspecs + ' --> ' + newdirspecs
else:
print olddirspecs +' --> Not renamed'
for filename in filenames:
newfilespecs = dirpath + '/' + replace_all(filename,replacedict)
oldfilespecs = dirpath + '/' + filename
if newfilespecs != oldfilespecs :
#os.rename(oldfilespecs, newfilespecs)
print oldfilespecs + ' --> ' + newfilespecs
else:
print oldfilespecs +' --> Not renamed'
-
Vreemd dat hij het bij jouw niet doet.
Heb het maar even op m'n PC geprobeert en dan krijg ik dit als resultaat.
Zit niet zo veel renames in maar een paar spaties zijn toch veranderd.
[attach=1]
-
Ja maar dat zijn filerenames, die doen het wel, wat ik aan gaf is dat de directories niet gerenamed worden.
-
Die allereerste is een directory.
Je kunt dat alleen niet zien.
Als je dat beter wilt zien moet je de print statments even aanpassen door er Dir Rename: en File Rename: bij te zetten of zo iets.
for dirpath, dirnames, filenames in os.walk(path):
for dirname in dirnames:
newdirspecs = dirpath + '/' + replace_all(dirname,replacedict)
olddirspecs = dirpath + '/' + dirname
if newdirspecs != olddirspecs :
#os.rename(olddirspecs, newdirspecs)
print "Dir Rename: " + olddirspecs + ' --> ' + newdirspecs
else:
print "Dir Rename: "+olddirspecs +' --> Not renamed'
for filename in filenames:
newfilespecs = dirpath + '/' + replace_all(filename,replacedict)
oldfilespecs = dirpath + '/' + filename
if newfilespecs != oldfilespecs :
#os.rename(oldfilespecs, newfilespecs)
print "File Rename: " + oldfilespecs + ' --> ' + newfilespecs
else:
print "File Rename: " + oldfilespecs +' --> Not renamed'
-
Aha, ik zie het al, hij doet eerst alle dirs en daarna alle files.
Dat lijkt nu goed, echter ..... Voor het renamen van files in subdirs pakt hij nog de ongewijzigde dirnamen die echter vlak daarvoor net gewijzigd zijn.
:/
-
Hmm das een lastige.
Even nagedacht en de oplossing is eerst de files te doen en daarna de directories pas.
dus zo:
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
newfilespecs = dirpath + '/' + replace_all(filename,replacedict)
oldfilespecs = dirpath + '/' + filename
if newfilespecs != oldfilespecs :
#os.rename(oldfilespecs, newfilespecs)
print "File Rename: " + oldfilespecs + ' --> ' + newfilespecs
else:
print "File Rename: " + oldfilespecs +' --> Not renamed'
for dirname in dirnames:
newdirspecs = dirpath + '/' + replace_all(dirname,replacedict)
olddirspecs = dirpath + '/' + dirname
if newdirspecs != olddirspecs :
#os.rename(olddirspecs, newdirspecs)
print "Dir Rename: " + olddirspecs + ' --> ' + newdirspecs
else:
print "Dir Rename: "+olddirspecs +' --> Not renamed'
-
Dat werkt ook niet, volgens mij komt dat omdat hij de directorynamen pakt van voordat hij met renamen begint.
-
Ik denk dat hij het wel doet.
Het probleem is dat hij bij je test natuurlijk niet echt renamed.
Je zou even een aantal test directories en files moeten maken om het echt te kunnen testen.
Als het echt niet werkt moet ik iets bedenken om het bottum up te doen in plaats van top down.
Ik moet nu stoppen maar als je er niet uit komt, laat het even weten dan regel ik het morgen even.
-
nog even getest met een paar test dirs en files (tot 2 niveaus diep).
Hij doet het wel, maar niet recursief.
python ./renall.py
File Rename: ./renall.py --> Not renamed
File Rename: ./file level 0 --> ./file_level_0
Dir Rename: ./level 0 dir 1 --> ./level_0_dir_1
Dir Rename: ./level 0 dir 2 --> ./level_0_dir_2
-
Ok doen we het anders.
We lopen eerst bottom up door de directories om die te renamen en doen daarna alle files
print "*************************"
print "* Renaming directories *"
print "*************************"
print""
for dirpath, dirnames, filenames in os.walk(path, topdown=False):
for dirname in dirnames:
newdirspecs = dirpath + '/' + replace_all(dirname,replacedict)
olddirspecs = dirpath + '/' + dirname
if newdirspecs != olddirspecs :
#os.rename(olddirspecs, newdirspecs)
print "Dir Rename: " + olddirspecs + ' --> ' + newdirspecs
else:
print "Dir Rename: " + olddirspecs +' --> Not renamed'
print ""
print "********************"
print "* Renaming files *"
print "********************"
print""
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
newfilespecs = dirpath + '/' + replace_all(filename,replacedict)
oldfilespecs = dirpath + '/' + filename
if newfilespecs != oldfilespecs :
#os.rename(oldfilespecs, newfilespecs)
print "File Rename: " + oldfilespecs + ' --> ' + newfilespecs
else:
print "File Rename: " + oldfilespecs +' --> Not renamed'
-
Dit lijkt te werken.
Zit er een limiet aan het aantal niveau's in directory diepte?
Ik denk dat dit meer CPU belastend is dan de bash rename die ik normaal gebruik.
Maar bij het ontbreken daarvan in Busybox lijkt me dit een mooi alternatief.
Het wordt echt interessant als ik 10000en files hiermee met 1 run wil renamen (ja dat doe ik soms).
Bednakt voro je hulp tot zover.
-
Dezelfde limiet die het OS heeft, want os.walk is een os call.
Daarom zal de overhead wel meevallen denk ik.
Python heeft iets overhead dus bij het opstarten ben je wat tijd kwijt, maar meer niet.
Als je echt zoveel gaat renamen zou het misschien verstandig zijn de output naar een file te sturen in plaats van naar de console.
Kun je het later nog eens terug kijken.
fp = open("filesspecs")
fp.write("hier tekst" + variable)
-
Ja daar kwam ik dus nu net achter (te laat) want ik kon niet ver genoeg terug scrollen.
Maar zo op het eerste gezicht lijkt het script gedaan te hebben wat ik wil.
Hartelijk dank voor je hulp.
PS: Is er een logische plek waar je eigen python scripts neer te zetten in DSM? Ik heb het nu in /usr/loca/bin gezet maar als je het vanuit python aan roept moet je sowieso het absolute pad opgeven.
-
Persoonlijk zet ik ze altijd op een share neer, dan kan ik er vanuit m'n PC makkelijk bij.
-
Geweldige discussie hier. Ik kan geen nuttige informatie toevoegen, maar heb het wel met belangstelling gelezen.
Overigens gebruik ik zelf een PC programa RenameMaster als ik een reeks van bestanden volgens een bepaalde logica wil hernoemen. Dit is niet wat je zoekt, maar wel heel handig om bijvoorbeeld foto bestanden of documenten te hernoemen volgens met een logische naamgeving waarin bijvoorbeeld een datum of volgnummering moet zitten. Misschien hebben andere lezers die de Python oplossing te technisch vinden misschien iets aan.
-
Ja voor een PC en in mindere mate voor MAC zijn ontzettend veel programmas te vinden.
Dan ga je zelf niet het wiel uitvinden.
Het leuke van Python is dat het overal op draait en je geen moeilijke dingen als compileren en linken moet doen voor je iets hebt dat draait.
-
Helaas werkt het script niet meer.
Ik vermoed dat het met een van de laaste firmware updates 'kapot' is gegaan.
Traceback (most recent call last):
File "rename.py", line 9, in <module>
os.rename(File, NewFileSpecs)
OSError: [Errno 18] Invalid cross-device link
Is dit op te lossen? Ik heb zelf helaas geen python kennis.....
-
Ik denk dat je probeert te renamen van het ene volume naar een ander volume.
Dat kan os.rename niet.
Je zou os.rename(File, NewFileSpecs) kunnen vervangen door
shutil.move(File, NewFileSpecs)
Wel even de eerste regel veranderen isn:
import os, shutil
Ander kan hij die module niet vinden.
Als dit niet de oplossing is moet je even het hele script hier posten dan kan ik er wat error afhandeling voor je inbouwen.
-
ik zie het al, ik had per ongeluk een oude versie gebruikt.
ik heb hem gelijk weggegooit.
Tja normaal heb ik een standaard dir voor mij actieve scripts maar goed daar hebben we het in dit draadje al over gehad.
Sorry voor het ongemak en bedankt voor de hulp.