Portál AbcLinuxu, 4. května 2025 14:21

Hromadné zrušení diakritiky v adresářovém stromu

5.4.2005 01:36 | Přečteno: 4701× | linux

Už několikrát se mi stalo, že jsem potřeboval v adresářovém podstromu zrušit diakritiku, popř. nahradit mezery v názvech znakem "_". Nepodařilo se mi najít nějaký program, který je k tomu určený a "ruční" přejmenovávání mě už přestalo bavit. Proto, ač nejsem zkušený programátor v shellu, jsem si zkusil udělat skript, který výše zmíněné zvládne. Nevím, na kolik je moje řešení "čisté", nicméně jsem to zkoušel a k mé radosti skript udělal, co jsem od něj očekával. Proto jsem se rozhodl dát si ho do blogu jako svůj první zápis. :o) Zároveň budu rád, když mě ti zkušenější z vás třeba upozorní na mou chybu nebo možnost lepšího řešení.

Tak tedy: Skript je rozdělen do dvou souborů. První soubor s názvem start obsahuje jen příkaz find, který prohledává aktuální adresář a pro každou položku spouští skript diakritika s parametrem názvu položky:

soubor "start":
#!/bin/bash

find ./ -exec ./diakritika {} \;

Skript diakritika vypadá nějak následovně.

soubor "diakritika":
#!/bin/bash

if test -w "$1"
 then
  echo "-----------------------------------------------------------------"
  echo "Prejmenovavam soubor $1"
  JMENO=`echo $1 | sed 's/ě/e/g' | sed 's/š/s/g' | sed 's/č/c/g'| sed 's/ř/r/g'`
  JMENO=`echo $JMENO | sed 's/ž/z/g' | sed 's/ý/y/g' | sed 's/á/a/g' | sed 's/í/i/g'`
  JMENO=`echo $JMENO | sed 's/é/e/g' | sed 's/ú/u/g' | sed 's/ů/u/g' | sed 's/ó/o/g'`
  JMENO=`echo $JMENO | sed 's/ď/d/g' | sed 's/ť/t/g' | sed 's/ň/n/g'`
  JMENO=`echo $JMENO | sed 's/Ě/E/g' | sed 's/Š/S/g' | sed 's/Č/C/g'| sed 's/Ř/R/g'`
  JMENO=`echo $JMENO | sed 's/Ž/Z/g' | sed 's/Ý/Y/g' | sed 's/Á/A/g' | sed 's/Í/I/g'`
  JMENO=`echo $JMENO | sed 's/É/E/g' | sed 's/Ú/U/g' | sed 's/Ů/U/g' | sed 's/Ó/O/g'`
  JMENO=`echo $JMENO | sed 's/Ď/D/g' | sed 's/Ť/T/g' | sed 's/Ň/N/g'`
  JMENO=`echo $JMENO | sed 's/ /_/g'`
  echo "Na soubor:"
  echo $JMENO
   if [ "X$JMENO" != "X$1" ]
   then
     mv -f "$1" "$JMENO"
     if test -d "$JMENO"
     then
       find ./ -exec diakritika {} \;
     fi
   fi
 else
 echo "Nemas prava menit soubor/adresář!"
 echo "-----------------------------------------------------------------"
fi

Na začátku skript otestuje, zda je povolen soubor/adresář pro zápis. Pokud ano, odstraní háčky a čárky (náhradí se písmenem bez háčku/čárky), mezeru nahradí podtržítkem. Pokud je nový název různý od starého (soubor obsahoval diakritiku) přejmenuje soubor/adresář na nové jméno. Na problém jsem narazil, když měněnou položkou byl adresář. U adresáře, který obsahoval diakritiku, se diakrikika odstranila, ale skript už dál neprocházel jeho podstrom. To vyřešil poslední test -- je-li měněnou položkou adresář, je v podstatě znovu spuštěn start. Řádky začínající echo pouze vypisují, s čím skript pracuje a jejich smazáním by se možná urychlil (nevím, možná ne).

Ještě bych dodal, že skript samozřejmě nenahrazuje veškerou diakritiku, ale jen tu běžně používanou v češtině (snad jsem na něco nezapomněl). Další náhrady by se ale daly dopsat. Skript jsem testoval jen na malém podstromu asi o třech úrovních, takže nevím, jak bude pracovat při složitějších strukturách.

Pro použití skriptu stačí oba soubory nahrát do adresáře, v jehož podstromu chceme odstranit diakritiku a spustit ./start

Budu rád za vaše náměty na lepší řešení. Bude-li někdo skript zkoušet -- doporučuji nejprve na neškodných datech. Jak jsem psal v úvodu, nejsem v žádném případě zkušený programátor v shellu, a proto nevím, zda nemůže mít tento skript "vedlejší účinky"...

       

Hodnocení: 33 %

        špatnédobré        

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře. , Tisk

Vložit další komentář

5.4.2005 03:51 Honza Král | skóre: 3 | Praha
Rozbalit Rozbalit vše sed
Odpovědět | Sbalit | Link | Blokovat | Admin
lepsi nez spousta prikazu s/x/y/ je lepsi pouzit jeden: bud sed -e 'y/abcd/ABCD/' nebo tr 'abcd' 'ABCD'
5.4.2005 07:38 kavol
Rozbalit Rozbalit vše Re: sed
jo, když jsem na to koukal, tak jsem se taky divil, proč používá sed a ne tr :-) ... nicméně pak jsem si vzpomněl, jak jsme to řešili s kámošem, a že asi nejlepší je použít program recode (aneb proč opisovat do tr půlku kódové tabulky, když už to udělal někdo za mě a flexibilněji, mohu překódovat z více různých sad; pravda, trošku kanón na vrabce ;-))

řešení s findem je imho blbost, stejně jako používat na to dva skripty; máme to vyřešené pomocí rekursivní funkce

bohužel teď nemám po ruce příslušný zdroják, takže jenom nastíním ideu: procházení se děje pomocí for *, testuje se, zda jde o adresář, a pokud ano, tak funkce zavolá sama sebe na ten adresář, potom dojde k přejmenování (tzn. adresář se přejmenuje, až se z něj vyleze ven, nedojde k nekonsistenci)

p.s. a odstraňování diakritiky považuju za pěknou blbost - zrušením všech ne-ASCII (7bit) znaků bych uvedl do absolutního chaosu např. svoje veškeré ruské písničky - pojmenované samozřejmě v azbuce, od čeho máme UTF8 :-)

p.p.s. taky vás tak štvou lidi, co v angličtině (i jinde) místo apostrofu píšou čárku nad písmenem, takže místo ASCII se na jejich věc (obvykle právě jméno souboru) použije nejbližší sada, která tento "spacing modifier" obsahuje, a tudíž prudce klesá strojová zpracovatelnost (objevuje se problém s překódováním a především to, že čárka není apostrof - třeba konverze ohraničení apostrofy na korektní uvozovky)? :-(
5.4.2005 08:34 kavol
Rozbalit Rozbalit vše Re: sed
eh, nějak jsem přehlíd, že už je tu i realizace toho, co navrhuju (až na to recode ;-)) ... mno, řekl bych, že by se to dalo i zjednodušit, ale tak nějak jsem to myslel ...
5.4.2005 04:05 Honza Král | skóre: 3 | Praha
Rozbalit Rozbalit vše redundance
Odpovědět | Sbalit | Link | Blokovat | Admin
s tim findem je to divny, co kdyz prejmenujes adresar, pak vubec nepujdou zmenit soubory uvnitr... (a krome toho je pak zbytecna ta tva rekurze)...

navrhuju tohle:
#!/bin/bash

function strip_diak {
  echo "$1" | tr 'ěščřž ..' 'escrz_..'
}

function diak {
  new_name="$( strip_diak "$1" )"
  mv -f "$1" "$new_name" || return 1

  cd "$new_name" || return 1

  for fajl in *; do
    if [[ -d "$fajl" ]]; then
      diak "$fajl"
    else
      new_name="$( strip_diak "$fajl" )"
      if [[ "$new_name" != "$fajl" ]]; then
        mv -f "$fajl" "$new_name" || echo "mv error" && return 1
      fi
    fi
  done

  return 0
}

diak "${1:-$PWD}" || exit 1

exit 0
Valoun avatar 5.4.2005 11:33 Valoun | skóre: 30 | blog: Psavec | Středočeský kraj
Rozbalit Rozbalit vše Re: redundance
To je vsechno moc pekny ja ovsem narazil na to, ze nevim jak do toho skriptu
echo "$1" | tr 'ěščřž ..' 'escrz_..'
zapsat, ze chci prelozit patricne unikodove znaky jako jsou äåöõü atd.
23.5.2005 16:16 Krakonoš | skóre: 17 | Nová Ves v Horách
Rozbalit Rozbalit vše Re: redundance
Tak tohle sem presne potreboval. Ale nejako se mi nepovedlo to dat do chodu, ale ziskal jsem inspiraci a za chvilenku napsal vlastni scriptik, ktery resi

prejmenovani a rekurzivni prochazeni aktualniho stromu (stacii :]) kolizi jmen - pridava pripadne nakonec .cislo pokud je to nutne

Tak snad sem na nic nezapomel :

#!/bin/bash

function strip_diak { echo "$1" | tr '¿¿¿¿¿ýáíé¿¿¿¿¿¿¿¿ÝÁÍÉ¿¿¿' 'escrzyaiedtnESCRZYAIEDTN' }

function rename { for file in *; do new_name="$( strip_diak "$file" )" if [[ "$file" != "$new_name" ]]; then if [[ -e "$new_name" ]]; then n=0 while [[ -e "$new_name.$n" ]]; do n=`expr $n + 1` done new_name="$new_name.$n" fi mv "$file" "$new_name" fi if [[ -d "$new_name" ]]; then cd $new_name rename cd .. fi done }

rename

exit 0

ou,..koukam, ze to neskouslo ty znaky,...tos nevadi, si je tam dopishte :]
5.4.2005 08:59 Jiri Bajer | skóre: 34 | blog: Sarimuv koutek | Praha
Rozbalit Rozbalit vše Whitespaces
Odpovědět | Sbalit | Link | Blokovat | Admin
IMHO se find -print nedokaze korektne vyporadat s whitespaces v nazvech souboru - nebylo by lepsi pouzit find -print0 | xargs --null?

Tak jak tak: diky za prispevek, podle me je cennejsi komplet zdrbnout tvuj kod a vymyslet lepsi, nez mlcet a nechat vsechny, at znovu vynalezaji kolo! B-)
5.4.2005 11:29 Michal Marek (twofish) | skóre: 55 | blog: { display: blog; } | Praha
Rozbalit Rozbalit vše Práva
Odpovědět | Sbalit | Link | Blokovat | Admin
Na přejmenování souboru nepotřebuju právo zápisu do toho souboru ;-)
5.4.2005 11:30 honza
Rozbalit Rozbalit vše existuje soubor ?
Odpovědět | Sbalit | Link | Blokovat | Admin
Co se stane mám-li v jednom adresáři vykaz.txt a výkaz.txt :-)
5.4.2005 14:19 Zbyněk Petr (Zboňa) | skóre: 6 | blog: zbona | Brno / Vyškov
Rozbalit Rozbalit vše Re: existuje soubor ?
Aha, tak na to jsem pozapomněl. :-)
5.4.2005 15:21 kavol
Rozbalit Rozbalit vše Re: existuje soubor ?
používání -f je špatné, špatné, špatné ...

... mamííí, ploč ťam má ťeň páň -f míšto -i? :-)
5.4.2005 15:10 VícNežNic | skóre: 42 | blog: Spáleniště | Ne dost daleko
Rozbalit Rozbalit vše Hm
Odpovědět | Sbalit | Link | Blokovat | Admin
Kdyby měl někdo dojem, že tohle je moc složité a nevadilo by mu zjednodušit zadání na: ,,hromadné zrušení adresářového stromu``, pak milerád pomohu radou :-)
Copak toho není dost?
5.4.2005 18:27 Zdeněk Burda | skóre: 61 | blog: Zdendův blog | Praha
Rozbalit Rozbalit vše Re: Hm
Otočení kolečkem nahoru přepíná plochu směrem doprava

Ať žije výchozí nastavení WindowMakeru :-)
-- Nezdar není hanbou, hanbou je strach z pokusu.
18.1.2013 23:19 Lukas
Rozbalit Rozbalit vše Re: Hromadné zrušení diakritiky v adresářovém stromu
Odpovědět | Sbalit | Link | Blokovat | Admin
Ahoj vim ze tohle je hodne stare ale nevite nekdo jak se ta diakritika da odstranit pres PHP jo a jinak momentalne pouzivam XAMPP server a Windows 7... je sice hezke ze pres iconv a spoustu dalsi funkci odstranim diakritiku ale problem je s PHP rename funkci ve ktere nemohu prejmenovavat slozky a soubory s diakritikou..takze hlavni problem je prave v prejmenovani dejte mi prosim vedet na email: lukas.stribrny@hotmail.com

Založit nové vláknoNahoru

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.