Czasem zdarza się, że mamy ogromną ilość plików zapisanych WIELKIMI literami, a z jakiegoś powodu chcemy zamienić je na małe. Jeżeli tych plików jest kilka, możemy zmienić ich nazwy ręcznie. Ale co będzie jeśli musimy zmienić ponad 1000 plików, które są zdjęciami z wakacji? Z pomocą przyjdzie nam polecenie tr. Jest to narzędzie, za pomocą którego można zmieniać i usuwać znaki. Polecenie to czyta ze standardowego wejścia i wynik wypisuje na standardowe wyjście.

Zaczynając przygodę z poleceniem tr poznajmy jego podstawowe funkcje. Wydając polecenie: tr abc xyz zamienimy każdy nak występujący na i-tym miejscu w abc jest zastępowany znakiem występującym na i-tym miejscu w xyz. Zatem każde a na wejściu zamieni się na x, b na y i c na z. Zatem sprawdźmy, czy to prawda:

paszczak000@hell:~$ echo Ala ma kota i lubi go całować | tr abc xyz
Alx mx kotx i luyi go zxłowxć

Jak widać polecenie tr poprawnie zamieniło znaki. Ale to nie wszystko. Możemy wykorzystać tr do usuwania znaków podanych na wejściu. Do tego służy parametr -d. Wydając polecenie tr -d abc skasujemy wszystkie znaki abc jakie znajdą się na wejściu. Jeśli dodamy parametr -c, spowodujemy, że usuniemy wszystkie znaki, które nie podaliśmy w parametrze. Przykład:

paszczak000@hell:~$ echo Ala ma kota i lubi go całować | tr -d a
Al m kot i lubi go cłowć

paszczak000@hell:~$ echo Mam na imie Piotrek. Mój numer to telefonu to 948-234-446-32 | tr -cd 0123456789
94823444632

Jak widać w pierwszym przykładzie usunęliśmy wszystkie literki a. Natomiast w drugim chcieliśmy wyciągnąć sam numer telefonu z ciągu znaków. tr usunął wszystkie znaki poza cyframi (0123456789).

Znając podstawowe funkcje polecenia, możemy przystąpić do próby zmiany wielkich liter na małe. W Internecie dostępne jest wiele tego typu przykładów, dlatego przyjrzymy im się z bliska. Najprostszą metodą jest wykorzystanie skryptu:

for file in * ; do
	mv "$file" `echo "$file" | tr '[A-Z]' '[a-z]'`
done

Pętla for pobierze nam wszystkie pliki w danym katalogu, po czym poleceniem mv oraz tr zmienimy im nazwę. W nawiasach kwadratowych podany jest zakres znaków jakie mają zostać zamienione. Możemy delikatnie zmodyfikować skrypt i wykorzystać klasy znaków dla polecenia tr:

for file in *
do
	mv $file `echo $file | tr [:upper:] [:lower:]`
done

W tym wypadku wykorzystując klasy upper i lower Wykorzystując klasy możemy określić jakie zakresy znaków mają być brane pod uwagę. Mamy do dyspozycji:

  • alnum – znaki alfanumeryczne
  • alpha – litery
  • cntrl – znaki kontrolne
  • digit – cyfry
  • graph – znaki graficzne, bez spacji
  • lower – małe litery
  • print – znaki pisarskie w tym spacja
  • punct – znaki interpunkcyjne
  • space – spacje, białe znaki
  • upper – wielkie litery
  • xdigit – znaki hexadecymalne

Taką samą operację (zmiana wielkich liter na małe) możemy wykonać z wykorzystaniem Perla w skrypcie:

for file in `ls -1|perl -ne 'print "$_" if (/[A-Z]/);'`
do
	mv ${file} `echo ${file}|perl -ne 'chomp;print "$_" if (tr/A-Z/a-z/);'`;
done

W Internecie dostępne są również inne modyfikacje powyższych skryptów. Jedną z nich jest kod napisany przez Johna Dubois, a następnie zmodyfikowany przez Chet Ramey:

#!/bin/bash
#
#  Changes every filename in working directory to all lowercase.
#
#  Inspired by a script of John Dubois,
#+ which was translated into Bash by Chet Ramey,
#+ and considerably simplified by the author of the ABS Guide.

for filename in *                # Traverse all files in directory.
do
fname=`basename $filename`
n=`echo $fname | tr A-Z a-z`  # Change name to lowercase.
if [ "$fname" != "$n" ]       # Rename only files not already lowercase.
then
mv $fname $n
fi
done

exit $?

Niestety skrypt ten nie poradzi sobie z plikami, które zawierają różnego rodzaju białe znaki oraz znak nowej linii. Stephane Chazelas zaproponował następujące rozwiązanie:

# The above script will not work on filenames containing blanks or newlines.
# Stephane Chazelas therefore suggests the following alternative:

for filename in *    # Not necessary to use basename,
# since "*" wont return any file containing "/".
do n=`echo "$filename/" | tr '[:upper:]' '[:lower:]'`
#                             POSIX char set notation.
#                    Slash added so that trailing newlines are not
#                    removed by command substitution.
# Variable substitution:
n=${n%/}          # Removes trailing slash, added above, from filename.
[[ $filename == $n ]] || mv "$filename" "$n"
# Checks if filename already lowercase.
done

exit $?

Polecenie tr jest bardzo przydatne jeśli chcemy usunąć z nazw naszych plików zbędne znaki lub ustandaryzować ich wielkość. Więcej informacji na temat tr, dostępne jest w manualu.

Podobne artykuły

  • Pingback: Masowe skalowanie obrazków | thecamels.org()

  • skrypt usuwajacy pol

    postanowilem zmodyfikowac nieco powyzszy plik i pozbawia on znaki diaktryczne i spacje z plikow – ja stosuje to do plikow uzytkownikow ktorzy trzymaja swoje dane na sambie i zapominaja ze zaleta jest nie stosowac powyzszych w nazwach plikow:

    <pre>#!/bin/bash

    # USUNIECIE POLSKICH LITER

    for filename in *

    do n=`echo "$filename/" | tr [:blank:] _ | tr "241" "A"|tr "261" "a"|tr "246" "S"|tr "266" "s"|tr "257" "Z"|tr "277" "z"|tr "254" "Z"|tr "274" "z"|tr "306" "C"|tr "346" "c"|tr "323" "O"|tr "363" "o"|tr "243" "L"|tr "263" "l"|tr "321" "N"|tr "361" "n"|tr "312" "E"|tr "352" "e"

    `

    n=${n%/}

    echo "JEST :> " $filename "ZMIENIAM NA :>" $n

    #sleep 1

    [[ $filename == $n ]] || mv "$filename" "$n"

    done

    exit $?</pre>

  • Pingback: Masowe skalowanie obrazków - OSWorld.pl()