Massnamnbyte på filer i given mapp med undermappar [LÖST]
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Massnamnbyte på filer i given mapp med undermappar [LÖST]
Har en massa filer med versaler i sina filändelser och vill ändra alla dessa till gemener utan att filnamnen i övrigt påverkas. Har inte lyckats få till det på något vettigt sätt. Ett misslyckat försök ledde till att samtliga tecken blev gemener, alltså inte bara filändelsen…
Senast redigerad av 3 Johnny Rosenberg, redigerad totalt 12 gång.
- ZX Spectrum
- Inlägg: 4905
- Blev medlem: 04 jan 2007, 22:58
- OS: Ubuntu
- Utgåva: Vet inte/ingen utgåva passar
- Ort: Göteborg
Re: Massnamnbyte på filer i given mapp med undermappar
Programmet metamorphose fixar ditt problem:
http://file-folder-ren.sourceforge.net/ ... ?page=Main
Du får upp flikarna Väljare|Huvud|Numrering|Datum och tid|Fel/varningar i programmet.
Det enda som behövs för att ändra filändelsen till gemener är Väljare och Huvud.
Välj mapp där dina filer ligger med Väljare och gå sen till Huvud-fliken.
Bocka ur "Namn" och bocka sen i "Filtyp". Fortsätt sen med att bocka i "Sök" och sen "modifiera". Till höger om modifiera kan man välja versaler eller gemener.
Genom att ändra här så kan man lätt se hur resultatet blir längst ner i programmet.
http://file-folder-ren.sourceforge.net/ ... ?page=Main
Du får upp flikarna Väljare|Huvud|Numrering|Datum och tid|Fel/varningar i programmet.
Det enda som behövs för att ändra filändelsen till gemener är Väljare och Huvud.
Välj mapp där dina filer ligger med Väljare och gå sen till Huvud-fliken.
Bocka ur "Namn" och bocka sen i "Filtyp". Fortsätt sen med att bocka i "Sök" och sen "modifiera". Till höger om modifiera kan man välja versaler eller gemener.
Genom att ändra här så kan man lätt se hur resultatet blir längst ner i programmet.
Jag vet vad jag vill, men vill inte det jag vet, men ändå vet jag ingenting och nu vet jag garanterat inte vad jag snackar om
Re: Massnamnbyte på filer i given mapp med undermappar
Jag slänger ihop ett bash-skript snabbt som fixar biffen. Vad säger ni om det här:
Där $1 är sökvägen till filerna, t.ex: ./script.sh "/home/username/files/"
Kod: Markera allt
#!/bin/bash
dir=$(echo "$1" | sed 's/\/ *$//')
ls -1 $dir > files.txt
while read file; do
file_extension=$(echo "$file" | grep -o "\.[^\.]*$" | tr '[:upper:]' '[:lower:]')
file_name=$(echo "$file" | sed 's/\.[^\.]*$//')
cp $dir/$file $dir/$file_name$file_extension
done < files.txt
Re: Massnamnbyte på filer i given mapp med undermappar
Kod: Markera allt
prename 's/(.+\.)(.+)$/$1\L$2/g' */*
ǁ A: Because it obfuscates the reading.
ǁ Q: Why is top posting so bad?
ǁ Q: Why is top posting so bad?
- Substrata
- Inlägg: 71
- Blev medlem: 13 apr 2010, 11:01
- OS: Arch Linux
- Utgåva: Vet inte/ingen utgåva passar
Re: Massnamnbyte på filer i given mapp med undermappar
Som vanligt när dmz har varit framme så behövs det inte sägas så mycket mer. Möjligen (i bash) så att underkataloger gås igenom rekursivt.
Kod: Markera allt
shopt -s extglob
prename 's/(.+\.)(.+)$/$1\L$2/g' **/*
Använd mktemp(1) för att skapa temporära filer. Här behöver du inte ta det steget eftersom ls | while ... fungerar, eller för den delen for n in *; do .... Om du vill kan du lösa åtminstone delar av substitueringen direkt i bash, till exempel ${1/%\//} för att skippa en eventuell sista /; se Parameter Expansion i manualen.ubot skrev:Vad säger ni om det här:Kod: Markera allt
#!/bin/bash dir=$(echo "$1" | sed 's/\/ *$//') ls -1 $dir > files.txt while read file; do file_extension=$(echo "$file" | grep -o "\.[^\.]*$" | tr '[:upper:]' '[:lower:]') file_name=$(echo "$file" | sed 's/\.[^\.]*$//') cp $dir/$file $dir/$file_name$file_extension done < files.txt
Re: Massnamnbyte på filer i given mapp med undermappar
Jag funderade också på vad /** kallades. Relativt nytt (Bash4?).
Jag brukar föredra att använda find direkt, men i vissa fall kan det ju vara användbart, som här.
Jag brukar föredra att använda find direkt, men i vissa fall kan det ju vara användbart, som här.
ǁ A: Because it obfuscates the reading.
ǁ Q: Why is top posting so bad?
ǁ Q: Why is top posting so bad?
Re: Massnamnbyte på filer i given mapp med undermappar
Se där. Jag slängde bara ihop ett bash-skript i all hast. dmz lösning ser ju smidig ut.
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
Tack för alla svar!
Och där står det:
När jag skriver man prename får jag upp hjälp om rename som jag använt ett antal gånger och det verkar ju vara samma sak som prename. Vad är annars skillnaden (i Ubuntu) på rename och prename? Båda verkar ju acceptera perl-uttryck.
(.+\.) – Ett eller flera valfria tecken följt av en punkt?
(.+) – Ett eller flera valfria tecken?
$ – Ovanstående ska vara i slutet på textsträngen?
$1 – Resultatet av ”(.+\.)” ovan?
\L – Lower case? I så fall, är upper case \U?
$2 – Resultatet av ”(.+)” ovan?
g – Ja, vad betyder detta egentligen?
Vad är det för skillnad på ”**/*” och på ”*/*”? Båda verkar vara sökvägen där namnbytena ska äga rum och jag kan då tänka mig att ”*/*” betyder ”här och i alla undermappar” eller liknande, men vad betyder då ”**/*”?
Om mina antaganden är riktiga, skulle följande uttryck säkerställa att alla filnamn i aktuellt mapp med undermappar har inledande versal?
Eller är jag ute och cyklar som vanligt? Om inte, så borde följande säkerställa inledande versal och filändelser i gemener, eller hur?
Har aldrig sett shopt förut så jag testade man shopt men det finns ingen manualsida för shopt, tydligen. Märkligt, för jag hittade en på nätet…Substrata skrev:Som vanligt när dmz har varit framme så behövs det inte sägas så mycket mer. Möjligen (i bash)så att underkataloger gås igenom rekursivt.Kod: Markera allt
shopt -s extglob prename 's/(.+\.)(.+)$/$1\L$2/g' **/*
Och där står det:
Visserligen är jag mer intresserad av att spela gitarr än att fåna mig med datorer, men jag fattar faktiskt inte vad som menas med detta. Kan någon förklara för en hjärndöd gamling?extglob – If set, the extended pattern matching features described above are enabled.
När jag skriver man prename får jag upp hjälp om rename som jag använt ett antal gånger och det verkar ju vara samma sak som prename. Vad är annars skillnaden (i Ubuntu) på rename och prename? Båda verkar ju acceptera perl-uttryck.
Detta ser ju lite rörigt ut för en hjärndöd stackare som jag, så jag tror jag behöver en liten förklaring… Förstår ju att ”s” står för ”substitute” men sedan är det mesta gissningar:'s/(.+\.)(.+)$/$1\L$2/g'
(.+\.) – Ett eller flera valfria tecken följt av en punkt?
(.+) – Ett eller flera valfria tecken?
$ – Ovanstående ska vara i slutet på textsträngen?
$1 – Resultatet av ”(.+\.)” ovan?
\L – Lower case? I så fall, är upper case \U?
$2 – Resultatet av ”(.+)” ovan?
g – Ja, vad betyder detta egentligen?
Vad är det för skillnad på ”**/*” och på ”*/*”? Båda verkar vara sökvägen där namnbytena ska äga rum och jag kan då tänka mig att ”*/*” betyder ”här och i alla undermappar” eller liknande, men vad betyder då ”**/*”?
Om mina antaganden är riktiga, skulle följande uttryck säkerställa att alla filnamn i aktuellt mapp med undermappar har inledande versal?
Kod: Markera allt
prename 's/(.^)(.+)/\U$1$2/g' **/*
Kod: Markera allt
prename 's/(.^)(.+\.)(.+)/\U$1$2\L$3/g' **/*
Senast redigerad av 1 Johnny Rosenberg, redigerad totalt 5 gånger.
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
Kanske, fast nu fanns det ju en anledning till att jag ställde frågan i terminalforumet…ZX Spectrum skrev:Programmet metamorphose fixar ditt problem

Klarar ovanstående program att byta namn rekursivt, förresten? Brukar använda GPRename annars och den bryr sig inte om innehållet i några undermappar, vad jag vet.
Re: Massnamnbyte på filer i given mapp med undermappar
./* matchar allt i nuvarande katalog. ./** matchar allt i nuvarande katalogJohnny Rosenberg skrev:extglob – If set, the extended pattern matching features described above are enabled.
rekursivt. Dvs, som -r-flaggan till många applikationer, när en katalog
påträffas så stiger vi in i den också och utför den operation som skall ske.
rename tillhör util-linux-ng, prename tillhör Perl. I vissaJohnny Rosenberg skrev: När jag skriver man prename får jag upp hjälp om rename som jag använt ett antal gånger och det verkar ju vara samma sak som prename. Vad är annars skillnaden (i Ubuntu) på rename och prename? Båda verkar ju acceptera perl-uttryck.
distributioner har man insett att rename är värdelöst och symlinkar prename till
rename.
(.+\.) – Ett eller fler av valfritt tecken (utom \n), fram till den första's/(.+\.)(.+)$/$1\L$2/g'
punkten. () runt uttrycket lagrar resultatet av matchningen i en capture group.
Om det matchar så lagras det i variabeln $1.
(.+) – Ett eller fler av valfritt tecken (utom \n).
$ – End of line *
$1 – Resultatet av den första grupperade matchningen
\L – Lowercase from here. \U är uppercase.
$2 – Resultat av den andra grupperade matchningen
g - Utför matchningen globalt
Nej, då kan du användaJohnny Rosenberg skrev: Om mina antaganden är riktiga, skulle följande uttryck säkerställa att alla filnamn i aktuellt mapp med undermappar har inledande versal?Kod: Markera allt
prename 's/(.^)(.+)/\U$1$2/g' **/*
Kod: Markera allt
s/^(.)(.+)/\U$1\E$2/g
Nej. Det är faktiskt inte svårare än så här:Johnny Rosenberg skrev: Eller är jag ute och cyklar som vanligt? Om inte, så borde följande säkerställa inledande versal och filändelser i gemener, eller hur?Kod: Markera allt
prename 's/(.^)(.+\.)(.+)/\U$1$2\L$3/g' **/*
Kod: Markera allt
s/^(.)(.+)$/\U$1\E\L$2/g
begagna dig av.
För att lära dig reguljära uttryck rekommenderas perldoc perlretut och
perldoc perlre.
ǁ A: Because it obfuscates the reading.
ǁ Q: Why is top posting so bad?
ǁ Q: Why is top posting so bad?
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
dmz skrev: Nej. Det är faktiskt inte svårare än så här:Kod: Markera allt
[/quote] Hm… inte? Testade (med -n) och här är ett exempel på hur det fungerade: [quote]bin/opera-widget-mastermind renamed as Bin/opera-widget-mastermind[/quote] Inte riktigt det jag var ute efter… Notera att ”opera” fortfarande har gemen första bokstav. Ska experimentera vidare…
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
Okej, men varför föreslogs då ”**/*”?dmz skrev:./* matchar allt i nuvarande katalog. ./** matchar allt i nuvarande katalog
rekursivt. Dvs, som -r-flaggan till många applikationer, när en katalog
påträffas så stiger vi in i den också och utför den operation som skall ske.
Re: Massnamnbyte på filer i given mapp med undermappar
Ah. Ja, om du skall göra rekursivt så får du matcha efter den sista /:Johnny Rosenberg skrev: Hm… inte? Testade (med -n) och här är ett exempel på hur det fungerade:Inte riktigt det jag var ute efter… Notera att ”opera” fortfarande har gemen första bokstav.bin/opera-widget-mastermind renamed as Bin/opera-widget-mastermind
Ska experimentera vidare…
Kod: Markera allt
s;/(.)(.+);/\U$1\E\L$2;g;' */*
uppnå, alternativt använda två olika regex till prename.
ǁ A: Because it obfuscates the reading.
ǁ Q: Why is top posting so bad?
ǁ Q: Why is top posting so bad?
- Substrata
- Inlägg: 71
- Blev medlem: 13 apr 2010, 11:01
- OS: Arch Linux
- Utgåva: Vet inte/ingen utgåva passar
Re: Massnamnbyte på filer i given mapp med undermappar
Dokumentation för shopt finns i manualsidan för bash. Men jag var visst slarvig, för det ska vara. Ur dokumentationen:
Kod: Markera allt
shopt -s globstar
Vid ett par tester så tillför inte **/* något över **. Före jag gräver ned mig av rodnad för detta misstag, så ursäktar jag mig med att **/* är syntaxen i zsh.The special pattern characters have the following meanings:
* Matches any string, including the null string. When the globstar shell option is
enabled, and * is used in a pathname expansion context, two adjacent *s used as a sin‐
gle pattern will match all files and zero or more directories and subdirectories. If
followed by a /, two adjacent *s will match only directories and subdirectories.

- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
Exempel på resultat:dmz skrev:Det är nog enklare att skriva ett enkelt perlscript specifikt för det du villKod: Markera allt
s;/(.)(.+);/\U$1\E\L$2;g;' */*
uppnå, alternativt använda två olika regex till prename.
Attans…PDFStudio/DefaultSettings_fr.xml renamed as PDFStudio/Defaultsettings_fr.xml
Men det känns ändå inte helt omöjligt… men nu orkar jag inte tänka mer på detta ikväll…
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
Har nu testat följande:
Ingen av dem letar sig ner till mer en en enda undermapp. Är det jag som missuppfattat allt som vanligt? Snart ger jag upp och kombinerar prename med find…
Kod: Markera allt
prename -n 's;/(.)(.+);/\U$1\E$2;g;' */** > Namnbytestest
Kod: Markera allt
prename -n 's;/(.)(.+);/\U$1\E$2;g;' **/* > Namnbytestest
Kod: Markera allt
prename -n 's;/(.)(.+);/\U$1\E$2;g;' */* > Namnbytestest
- Substrata
- Inlägg: 71
- Blev medlem: 13 apr 2010, 11:01
- OS: Arch Linux
- Utgåva: Vet inte/ingen utgåva passar
Re: Massnamnbyte på filer i given mapp med undermappar
Detta fungerar i bash här, för att lista samtliga underkataloger och dess filer.
Det blir dock något mer komplicerat om man vill skippa katalogerna i listningen. Exempel.
Övergår man till find så kan det se ut så här.
Notera dock att det blir fel när filnamnen innehåller tomrum, eftersom shellet då expanderar till flera argument. Om du har en fil som heter "a b" så sker expandering till echo "a" "b" i den senaste listningen. Ungefär här börjar min preferens för att låta shellet hitta filerna, i stället för att gå genom find. Men det finns förstås lösningar.
Med sistnämnda kodstycke kan du ersätta echo med prename. Ett problem är dock att IFS (internal field separator) är satt till radbrytning och inte allmänt tomrum (som inkluderar mellanslag, tab, radbrytning), vilket skulle kunna ge ett udda beteende efteråt om du inte återställer IFS. Poängen är att det finns en del gotchas.
Ovanstående bitar gäller dock bara om man vill lägga alla filer som argument till en körning av programmet. Har man inte det behovet, som med prename, så går följande bra.
Kod: Markera allt
shopt -s globstar
echo **
Kod: Markera allt
echo $(for n in **; do [ -f "$n" ] && echo "$n"; done)
Kod: Markera allt
echo $(find . -type f)
Kod: Markera allt
IFS=$'\n'
echo $(find . -type f)
Ovanstående bitar gäller dock bara om man vill lägga alla filer som argument till en körning av programmet. Har man inte det behovet, som med prename, så går följande bra.
Kod: Markera allt
find . -type f -exec echo {} \;
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
Bara la märke till att du plötsligt skrev ”;” istället för ”/”. Antar att det var för att göra det mer lättläst, eftersom det hade blivit en hel skog av ”/” annars, men varför använder man inte alltid ”;” istället?dmz skrev:Ah. Ja, om du skall göra rekursivt så får du matcha efter den sista /:Kod: Markera allt
s;/(.)(.+);/\U$1\E\L$2;g;' */*
Har knåpat ihop ett litet skript nu i alla fall, som ska fixa lite med namnbyten av mina av misstag namnbytta filer. Funderar på om jag ska våga köra den. Visserligen har jag säkerhetskopior på berörda filer (och alla andra filer också, för den delen), men det tar ju ganska lång tid att lägga tillbaka cirka 30 GiB från en extern USB-disk.
Jag har i alla fall en fil som jag kallar Egennamn-egennamn som följer följande mall:
Några exempel direkt ur filen:namn-med-gemener\tNamn-på-önskat-sätt
Kom förresten på att [:upper:] och [:lower:] inte funkar med å, ä och ö, så för att konvertera dessa var jag tvungen att köra ”y/abc…åäö/ABC…ÅÄÖ/” istället.johnny Johnny
Sr SR
sr SR
Gps GPS
gps GPS
östersund Östersund
Lite jobbigt också att de reguljära uttrycken inte funkar likadant i exempelvis prename och sed och så vidare. Exempelvis verkar inte ”$1”, ”$2” och så vidare funka i sed, utan där skulle man visst ha, vad var det? ”/1” respektive ”/2” istället? Eller var det ”\1” respektive ”\2”?
Nåja, hur som helst, så ser mitt lilla skript för närvarande ut så här, och det är nu ganska oflexibelt och fyller bara sitt syfte och inget mer, om det nu fungerar över huvud taget, vill säga:
Kod: Markera allt
#!bin/bash
File="Egennamn-egennamn"
Result="Namnbytestest"
Options="-v"
MyPath="$HOME/Eget/Media/"
if [ -f "$Result" ]; then
rm "$Result"
fi
# Inledande versal.
find "$MyPath" -type f -exec rename $Options 's;(.*/)(.)(.+);$1\U$2\E$3;g;' {} + > "$Result"
# Inledande versal för å, ä och ö.
for x in å ä ö
do
find "$MyPath" -type f -exec rename "$Options" 's;(.*/)$x(.+);$1\U$x\E$2;g;' {} + >> "$Result"
done
# Versaler och gemener i egennamn enligt listan i ”File”.
while read Line
do
Test=$(echo -e $Line | sed 's/\t.*//')
Replace=$(echo -e $Line | sed 's/.*\t//')
find "$MyPath" -type f -exec rename "$Options" 's;$Test;$Replace;g;' {} + >> "$Result"
done < "$File"
Jag är medveten om att skriptet kommer att ta oerhört lång tid att köra då det för varje namn ska gå igenom samtliga mina filer i mappen och dess undermappar. För närvarande innehåller listan 151 egennamn och det lär ju inte bli färre. De filer vars namn innehåller namn jag glömt ta med är förhoppningsvis inte fler än att jag kan ändra dem manuellt efter hand som jag upptäcker dem…
Allt detta för att återställa min egen klantighet efter att jag av misstag råkat konvertera alla mina filnamn i en viss mapp och undermappar till gemener…
- ZX Spectrum
- Inlägg: 4905
- Blev medlem: 04 jan 2007, 22:58
- OS: Ubuntu
- Utgåva: Vet inte/ingen utgåva passar
- Ort: Göteborg
Re: Massnamnbyte på filer i given mapp med undermappar
Ops, vilken miss.Johnny Rosenberg skrev:Kanske, fast nu fanns det ju en anledning till att jag ställde frågan i terminalforumet…ZX Spectrum skrev:Programmet metamorphose fixar ditt problem
![]()

Ja, metamorphose klarar av att byta namn på filer i underliggande mappar.Johnny Rosenberg skrev: Klarar ovanstående program att byta namn rekursivt, förresten? Brukar använda GPRename annars och den bryr sig inte om innehållet i några undermappar, vad jag vet.
Jag vet vad jag vill, men vill inte det jag vet, men ändå vet jag ingenting och nu vet jag garanterat inte vad jag snackar om
- Johnny Rosenberg
- Inlägg: 1256
- Blev medlem: 23 jun 2007, 16:18
- OS: Ubuntu
- Utgåva: 22.10 Kinetic Kudu
- Kontakt:
Re: Massnamnbyte på filer i given mapp med undermappar
Hm… testade nu mitt fina skript och det visade sig ju inte alls fungera och vad jag nu behöver veta är hur man slänger in variabler i reguljära uttryck. Följande, från mitt skript ovan, fungerar ju inte då:
Man kan tydligen inte bara slänga in ”$Test” och ”$Replace” hur som helst i ett reguljärt uttryck, så hur gör man då istället?
Dessutom är uttrycket ändå felaktigt. Vad jag skulle vilja ha är något i stil med följande, om jag vill byta ut alla ”hej” mot ”Hej”:
Men nu vill jag ju ersätta ”hej” respektive ”Hej” med variabler då jag vill hämta det jag vill byta ut respektive ersätta med ut en fil istället. Har kört fast lite där, tror jag…
Någon som kan leverera det ultimata tipset…?
Kod: Markera allt
while read Line
do
Test=$(echo -e $Line | sed 's/\t.*//')
Replace=$(echo -e $Line | sed 's/.*\t//')
find "$MyPath" -type f -exec rename "$Options" 's;$Test;$Replace;g;' {} + >> "$Result"
done < "$File"
Dessutom är uttrycket ändå felaktigt. Vad jag skulle vilja ha är något i stil med följande, om jag vill byta ut alla ”hej” mot ”Hej”:
Kod: Markera allt
's;([^a-zåäöA-ZÅÄÖ])hej([^a-zåäöA-ZÅÄÖ]);$1Hej$2;g;'
Någon som kan leverera det ultimata tipset…?
