Kirjoittaja Aihe: Tiedostojen nimi ongelma  (Luettu 2448 kertaa)

VOJ

  • Käyttäjä
  • Viestejä: 135
    • Profiili
Tiedostojen nimi ongelma
« : 17.01.16 - klo:12.14 »
Hei

Minulla on satoja tiedostoja joiden nimi on muotoa Filu_190915.txt. Numerot nimessä ovat päiväys muodossa ppkkvv. Haluaisin kerralla muuttaa nimet muotoon Filu_150919.txt eli päiväys muotoon vvkkpp. Tämä siksi että tiedostot saadaan päivämäärä järjestykseen nimen mukaan.

En vaan tiedä miten sen saa tehtyä muutoin kuin nimeämällä tiedoston kerrallaan. Varmasti on olemassa joku helpompikin keino vaan mikä?

Kaikki vinkit otetaan kiitollisena vastaan.

SuperOscar

  • Käyttäjä
  • Viestejä: 4000
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: Tiedostojen nimi ongelma
« Vastaus #1 : 17.01.16 - klo:12.45 »
Nimenmuutoksiin on ohjelmia kuten rename-niminen Perl-skripti (joka asentuu ainakin Debian 8:iin oletuksena) ja KRename-niminen KDE-ohjelma, mutta niilläkin voi joutua taiteilemaan irrottaakseen eri osat toisistaan.

Ainakin tämmöinen Python-skripti toimisi:

Koodia: [Valitse]
#!/usr/bin/env python3

import sys
import os
import re

pattern = re.compile('(.+)_(\d\d)(\d\d)(\d\d)(\..+)?')
for name in sys.argv[1:]:
    match = pattern.match(name)
    if match:
        prefix, day, mon, year, suffix = match.groups()
        new_name = '{}_{}{}{}{}'.format(prefix, year, mon, day, suffix)
        os.rename(name, new_name)
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11

nm

  • Käyttäjä
  • Viestejä: 16242
    • Profiili
Vs: Tiedostojen nimi ongelma
« Vastaus #2 : 17.01.16 - klo:12.57 »
SuperOscarin säännöllinen lauseke toimii siis Debianin/Ubuntun renamella näin:

Koodia: [Valitse]
rename 's/(.+)_(\d\d)(\d\d)(\d\d)(\..+)/$1_$4$3$2$5/' *.txt

petteriIII

  • Käyttäjä
  • Viestejä: 660
    • Profiili
Vs: Tiedostojen nimi ongelma
« Vastaus #3 : 18.01.16 - klo:02.35 »
Tulipa uutta, tattista nm. Käskystä vaan on tainnut unohtua g-kirjain pois. Siis käsky kuuluu: rename 's/(.+)_(\d\d)(\d\d)(\d\d)(\..+)/$1_$4$3$2$5/g' *.txt

Minä onnistuin aikaansaamaan niin paljon sotkuja ennenkuin alkoi toimia että täytyy varotella etteivät muut lankea samoihin kuoppiin:

Vaikka käsky kutsuu Perl-skriptiä niin kyllä sitä voi käyttää semmoisenaan BASH:issakin (tai DASH:iahan pääte taitaa olla), siis käsky toimii suoraan päätteestä annettuna. Mutta vaikka se onkin sangen "edistyksellinen" niin käsky toimii luotettavasti vain kun kaikki kansion tiedostot on nimetty aivan kuvatulla tavalla eikä kansiossa ei saa olla mitään muutakaan.
 
- mikäli tiedostonimissä on yksikin epäkelpo niin päädytään sotkuun. Siis kun kokeilet käskyä ensimmäisen kerran niin tee ensin backup jotta on mihin palata jos tulee suttajasekundaa.

jekku

  • Käyttäjä
  • Viestejä: 2624
    • Profiili
Vs: Tiedostojen nimi ongelma
« Vastaus #4 : 18.01.16 - klo:05.21 »
Lainaus
author=petteriIII link=topic=50057.msg383468#msg383468 date=1453077318
 
- mikäli tiedostonimissä on yksikin epäkelpo niin päädytään sotkuun. Siis kun kokeilet käskyä ensimmäisen kerran niin tee ensin backup jotta on mihin palata jos tulee suttajasekundaa.

Ns. "kantapään kautta" olen oppinut ja omaksunut tavan, että moisenkaltaisissa massaoperaatioissa kokeilen ensin ihan tulostaa komennot. Ja pitkät listat ohjaan tiedostoon.

Eli tuotos tyyliin :
Koodia: [Valitse]
...
mv File123.txt File321.txt
mv File456.txt File645.txt
...

Jos näyttää tolkulliselta niin ajaa ko. tiedoston..
(MItenkään väheksymättä ajantasaisia kopioita ;)

nm

  • Käyttäjä
  • Viestejä: 16242
    • Profiili
Vs: Tiedostojen nimi ongelma
« Vastaus #5 : 18.01.16 - klo:05.47 »
Tulipa uutta, tattista nm. Käskystä vaan on tainnut unohtua g-kirjain pois. Siis käsky kuuluu: rename 's/(.+)_(\d\d)(\d\d)(\d\d)(\..+)/$1_$4$3$2$5/g' *.txt

Kyllä sen pitäisi toimia ilman g:tä, jota tarvitaan silloin, kun halutaan sallia useat saman lausekkeen täsmäykset ja korvaukset saman merkkijonon (tiedostonimen) sisällä. Tässä tapauksessa tarvitaan vain yksi korvaus.

Koodia: [Valitse]
$ ls
Tiedosto1_190915.txt  Tiedosto2_201015.txt  Tiedosto3_211115.txt

$ rename 's/(.+)_(\d\d)(\d\d)(\d\d)(\..+)/$1_$4$3$2$5/' *.txt

$ ls
Tiedosto1_150919.txt  Tiedosto2_151020.txt  Tiedosto3_151121.txt


Ns. "kantapään kautta" olen oppinut ja omaksunut tavan, että moisenkaltaisissa massaoperaatioissa kokeilen ensin ihan tulostaa komennot. Ja pitkät listat ohjaan tiedostoon.

Renamen tapauksessa muunnosten listaus ilman niiden suorittamista onnistuu parametreilla -v -n (eli --verbose ja --no-act):

Koodia: [Valitse]
rename -v -n 's/(.+)_(\d\d)(\d\d)(\d\d)(\..+)/$1_$4$3$2$5/' *.txt
Koodia: [Valitse]
Tiedosto1_190915.txt renamed as Tiedosto1_150919.txt
Tiedosto2_201015.txt renamed as Tiedosto2_151020.txt
Tiedosto3_211115.txt renamed as Tiedosto3_151121.txt

SuperOscar

  • Käyttäjä
  • Viestejä: 4000
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: Tiedostojen nimi ongelma
« Vastaus #6 : 18.01.16 - klo:10.10 »
Juuri noiden nimien mahdollisten epäsystemaattisuuksien takia teen yleensä hommat Pythonilla, missä voin pitää huolta siitä, että jollei tiedostonimi tarkalleen vastaa mallia, sille ei tehdä mitään vaan annetaan varoitus.
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11

petteriIII

  • Käyttäjä
  • Viestejä: 660
    • Profiili
Vs: Tiedostojen nimi ongelma
« Vastaus #7 : 22.01.16 - klo:11.55 »
Näppis ja hiiri olivat aikaisemmin vain osittain tolkuissaan mutta nyt ostin uudet ja taas mennään.

Tuosta nm:n esittämästä rename-komennosta tuli mieleen että saisikohan samaa "BASH_REMATCH"-tyyppistä toimintaa sovellettua sanan muuttamiseen sed:illä. Pähkäilyähän se tottumattomalta vaati, mutta onnistuihan se lopulta. Esimerkki muuttaa vvvv.kk.pp muodossa olevan päiväyksen muotoon pp.kk.vvvv:
Koodia: [Valitse]
vvvvkkpp="2016 01 20"; ppkkvvvv=$(echo "edessä saa olla mitähyvänsä tekstiä, vaikka epäkelpo päiväys $vvvvkkpp ja niin perässäkin" | sed 's/\([0-9][0-9][0-9][0-9]\)\(.\)\([0-9][0-9]\)\(.\)\([0-9][0-9]\)/\5\4\3\2\1/'); echo "$ppkkvvvv"
- välimerkiksi kelpaa mikähyvänsä merkki - ei sen piste täydy olla. Tulosteessa on oletuksena sama välimerkki kuin sisäänmenossakin mutta voi sen määrätäkin korvaamalla merkit 2 ja 4 sanassa \5\4\3\2\1/
- jos haluaa tulosteeseen vv kaksi digitisenä niin tuo: \(....\) muutetaan muotoon ..\(..\)
- noita takaisinpäin-viittauksia voi olla 9 kappaletta.
- jos välimerkki on välilyönti niin päiväys täytyy laittaa sulkuihin.
- siis tuota sed-käskyä voi käyttää kaikkien tiedostossa olevien päiväyksien muuttamiseen -> super-regex
- kun  ideaa käsittelee useasti osoittautuu se helppokäyttöiseksi muotiksi ja sitä voi soveltaa mihinvaan.
« Viimeksi muokattu: 22.01.16 - klo:14.07 kirjoittanut petteriIII »