Vinnaren i pepparkakshustävlingen!
2023-12-15, 01:37
  #1
Medlem
Lite trevande start med Python. Försöker göra ett Python skript som ska ersätta oönskade tecken i filnamn mot önskvärda alternativ, i angiven mapp (inkl alla undermappar).

Att byta ut t.ex. mellanslag i filnamn mot underscore är ju rätt lätt:
Kod:
import os, fnmatch

file_path = 'C:\\Python-scripts\\testmapp\\'

files_to_rename = fnmatch.filter(os.listdir(file_path), '*.*')

for file_name in files_to_rename:    
   os.rename(file_path + file_name, 
         file_path + file_name.replace(' ', '_'))
.. men nu kan det ju finnas flera oönskade tecken i samma filnamn.
Problemet jag får med scriptet ovan är att alla filer genomsöks genom
Kod:
files_to_rename = fnmatch.filter(os.listdir(file_path), '*.*')
.. och om man då lägger till fler tecken som ska bytas ut, typ:
Kod:
file_path + file_name.replace('+', 'plus'))
.. så hittar inte skriptet dom filer som hade mellanslag och redan ändrats med underscore istället för mellanslag, eftersom skriptet uppenbarligen söker efter dom filnamn som filerna först hette (förmodligen lagrar en lista nånstans då).

Mitt sätt att tänka blir då att först ersätta mellanslag med underscore:
Kod:
files_to_rename = fnmatch.filter(os.listdir(file_path), '*.*')

for file_name in files_to_rename:    
   os.rename(file_path + file_name, 
         file_path + file_name.replace(' ', '_'))
.. och sen läsa igenom hela mappstrukturen igen, och därefter köra loopen igen med en ny ersättning:
Kod:
files_to_rename = fnmatch.filter(os.listdir(file_path), '*.*')

for file_name in files_to_rename:    
   os.rename(file_path + file_name, 
         file_path + file_name.replace('+', 'plus'))
osv osv.
Men dels känns det här som barn-kod, och dels har jag en jäkla massa oönskade tecken som jag vill söka efter och ersätta mot angivna alternativ. Problemet är alltså att kunna hitta och ersätta flera oönskade tecken i ett och samma filnamn (om det finns). Känns som det borde finnas ett mer effektivt sätt att göra det här på än att upprepa samma kod hundra gånger?

Är även intresserad att göra samma sak för Mappnamn framöver.

Tackar för lite idéer och tips.
__________________
Senast redigerad av Marinerad65 2023-12-15 kl. 01:49.
Citera
2023-12-15, 06:33
  #2
Avstängd
Använd regex.. exempel:

Kod:
import re

# filnamn
filenames = ["example#1.txt", "test@file.csv", "data%20.json"]

# Definiera mönstret som ska ersättas (t.ex. ersätt #, @, % med ett understreck)
pattern = re.compile(r"[#@%]")

# Byt ut tecknen i varje filnamn
modified_filenames = [pattern.sub("_", filename) for filename in filenames]

print(modified_filenames)

I det här exemplet skapar re.compile(r"[#@%]") ett regexmönster som matchar något av tecknen #, @ eller %. Undermetoden används för att ersätta dessa tecken med ett understreck _ i vart och ett av filnamnen. Tillämpar denna ersättning på varje element i filnamnslistan.

Bara ett exempel men regex skulle jag säga är bättre väg att gå än att skriva massa regex då man kan tänka in rätt komplexa mönster och skriva allt mer koncist.

Ovan är bara förenklat som sagt, du använder ju os för att integrera med filsystem och re för regex. (import os & import re)

Kod:
import os
import re

directory = "path/to/your/directory"

pattern = re.compile(r"[#@%]")

files = os.listdir(directory)

modified_filenames = [pattern.sub("_", file) for file in files]

print(modified_filenames)

När du använder os.listdir(sökväg) listar den alla filer och kataloger i den katalog som anges av sökväg. Om du vill inkludera filer från underkataloger, måste du gå igenom dessa underkataloger rekursivt. Här är ett enkelt exempel som använder os.walk() för att inkludera filer från underkataloger:

Kod:
import os

# root folder
root_directory = "/home/user/documents"

# Gå igenom katalogen
for path, subdirs, files in os.walk(root_directory):
    for name in files:
        # Skriver ut sökvägen till varje fil
        print(os.path.join(path, name))

Typ ovan psuedo bör fungera för mappar/subfolders etc.
__________________
Senast redigerad av Dofehix 2023-12-15 kl. 06:43.
Citera
2023-12-15, 07:38
  #3
Moderator
vhes avatar
Om alla tecken skall ersättas med samma så funkar en enkel regexp replace (se inlägg ovan).

Om inte så kan du kanske använda str.translate.

Kod:
>>> table = str.maketrans({' ': '_', '+': 'plus', '&': 'ampersand'})
>>> 'a string with plus & space'.translate(table)
'a_string_with_plus_ampersand_space'

[edit]: Jag måste dock fråga varför du vill göra det här? Det känns som om du slåss mot symtomen på ett problem, inte problemet i sig. Varför är de här tecknen problematiska? Varför är de i så fall med i filnamnen från början?
__________________
Senast redigerad av vhe 2023-12-15 kl. 07:41.
Citera
2023-12-15, 08:37
  #4
Medlem
Enterprises avatar
Var det inte du som ställde exakt samma fråga men Powershell?
Jag upprepar min synpunkt på själva idén: den skapar en risk för att olika filer får samma filnamn med potentiellt oönskade effekter. Det är därför bra att kolla efter redan existerande namn och lägga till någon form av extra tecken (t.ex. nummer) vid konlikt.

Sen håller jag med om vhe:s grundfråga, vad är orsaken till ditt behov? Är det att filerna ska delas mellan två olika filsystem där det ena enbart klarar av ASCII?
Citera

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback