[Skrypt bash] Masowa zmiana nazw plików


#1

Witam.

Jako że pisanie skryptów w bashu to nie jest to w czym jestem dobry, proszę bardziej doświadczonych o pomoc.

Sytuacja wygląda tak: mam folder a w nim podfoldery. W tych podfolderach mogą być kolejne podfoldery itd. W każdym z tych folderów mogą znajdować się pliki których struktura wygląda tak:

zmienna1.stała.zmienna2

gdzie zmienna 1 i zmienna2 mogą zawierać dowolny ciąg znaków a stała zawsze jest taka sama.

Po wykonaniu skryptu nazwa pliku ma się zmienić na

zmienna1.stała0.stała.zmienna2

Wiem tylko tyle, że przeszukanie i sprawdzenie w którym katalogu/podkatalogu są pliki odpowiadające wzorcowi znajdę find'em, ale jak wykorzystać to do automatycznej zmiany nazw znalezionych plików?

Z góry dziękuję za wszelkie sugestie.


(Kaka') #2

Skrypt do testów (w celu stworzenia przykładowej struktury katalogów i plików):

kaka@debian:/tmp$ cat new_make.sh 

#!/bin/bash


DIR=/tmp/areh2

const="aaaa"


for i in `seq 1 10`

do

    mkdir -p $DIR/folder$i

done


for i in $DIR/*

do

    for x in `seq 1 10`

    do

        touch $i/$RANDOM.$const.$RANDOM

    done

done

kaka@debian:/tmp$

Docelowy skrypt:

kaka@debian:/tmp$ cat new_skr.sh 

#!/bin/bash


DIR=/tmp/areh2

const="aaaa"

const_2="bbbb"


for i in $DIR/*

do

    for x in $i/*$const*

    do

        b=`basename $x`

        read zm_1 zm_2 <<< ${b//$const/ }

        mv "$x" `dirname $x`/"$zm_1""$const_2"."$const""$zm_2"

    done

done

kaka@debian:/tmp$

Tworzenie nowych plików i katalogów (testowych) oraz wyświetlenie całej struktury:

kaka@debian:/tmp$ ls -la areh2

ls: nie ma dostępu do areh2: Nie ma takiego pliku ani katalogu

kaka@debian:/tmp$ ./new_make.sh

kaka@debian:/tmp$ tree areh2/

areh2/

├── folder1

│   ├── 11913.aaaa.13413

│   ├── 12160.aaaa.268

│   ├── 12481.aaaa.1674

│   ├── 12737.aaaa.30641

│   ├── 17032.aaaa.5354

│   ├── 21081.aaaa.3048

│   ├── 21756.aaaa.8385

│   ├── 22604.aaaa.5479

│   ├── 25455.aaaa.15569

│   └── 908.aaaa.6656

├── folder10

│   ├── 12278.aaaa.24781

│   ├── 12531.aaaa.18610

│   ├── 12553.aaaa.26293

│   ├── 13986.aaaa.21233

│   ├── 16762.aaaa.28565

│   ├── 18204.aaaa.3966

│   ├── 21641.aaaa.32199

│   ├── 27439.aaaa.5290

│   ├── 29034.aaaa.27661

│   └── 8559.aaaa.8375

├── folder2

│   ├── 12129.aaaa.8577

│   ├── 13968.aaaa.19321

│   ├── 14165.aaaa.14814

│   ├── 14706.aaaa.8526

│   ├── 24045.aaaa.2795

│   ├── 24694.aaaa.29560

│   ├── 27578.aaaa.11558

│   ├── 31307.aaaa.23101

│   ├── 6832.aaaa.21816

│   └── 8623.aaaa.31841

├── folder3

│   ├── 15083.aaaa.20257

│   ├── 16040.aaaa.17715

│   ├── 22351.aaaa.4508

│   ├── 23943.aaaa.31019

│   ├── 31148.aaaa.18629

│   ├── 3986.aaaa.28183

│   ├── 4512.aaaa.10586

│   ├── 556.aaaa.10129

│   ├── 6788.aaaa.1529

│   └── 8083.aaaa.6100

├── folder4

│   ├── 1489.aaaa.1911

│   ├── 15176.aaaa.32586

│   ├── 16175.aaaa.9943

│   ├── 21008.aaaa.19888

│   ├── 21119.aaaa.13175

│   ├── 2392.aaaa.6787

│   ├── 28505.aaaa.29442

│   ├── 30897.aaaa.27145

│   ├── 4206.aaaa.18799

│   └── 8962.aaaa.30663

├── folder5

│   ├── 10494.aaaa.24576

│   ├── 14809.aaaa.283

│   ├── 16862.aaaa.22270

│   ├── 17580.aaaa.8514

│   ├── 20989.aaaa.14835

│   ├── 31812.aaaa.22670

│   ├── 5834.aaaa.26151

│   ├── 7242.aaaa.28488

│   ├── 8160.aaaa.22255

│   └── 8738.aaaa.882

├── folder6

│   ├── 11308.aaaa.13465

│   ├── 14302.aaaa.29083

│   ├── 16917.aaaa.11936

│   ├── 17604.aaaa.9780

│   ├── 21554.aaaa.16289

│   ├── 22798.aaaa.17585

│   ├── 31556.aaaa.20960

│   ├── 31857.aaaa.5151

│   ├── 8647.aaaa.15904

│   └── 9013.aaaa.29253

├── folder7

│   ├── 10594.aaaa.8776

│   ├── 11100.aaaa.23506

│   ├── 11927.aaaa.24818

│   ├── 13583.aaaa.29967

│   ├── 14045.aaaa.447

│   ├── 17428.aaaa.32493

│   ├── 21599.aaaa.18679

│   ├── 24784.aaaa.14553

│   ├── 25158.aaaa.1911

│   └── 26280.aaaa.18213

├── folder8

│   ├── 15176.aaaa.2173

│   ├── 19330.aaaa.21758

│   ├── 21226.aaaa.14602

│   ├── 24804.aaaa.12936

│   ├── 28993.aaaa.25644

│   ├── 30956.aaaa.2067

│   ├── 3138.aaaa.27010

│   ├── 6525.aaaa.26555

│   ├── 7623.aaaa.5494

│   └── 9646.aaaa.17982

└── folder9

    ├── 17836.aaaa.16299

    ├── 18434.aaaa.389

    ├── 2123.aaaa.10130

    ├── 21589.aaaa.11375

    ├── 29964.aaaa.5841

    ├── 31073.aaaa.1026

    ├── 3974.aaaa.25045

    ├── 409.aaaa.7554

    ├── 4139.aaaa.6583

    └── 5544.aaaa.28749


10 directories, 100 files

kaka@debian:/tmp$

Podobnie jak wyżej - przedstawienie działania docelowego skryptu:

kaka@debian:/tmp$ ./new_skr.sh

kaka@debian:/tmp$ tree areh2/

areh2/

├── folder1

│   ├── 11913.bbbb.aaaa.13413

│   ├── 12160.bbbb.aaaa.268

│   ├── 12481.bbbb.aaaa.1674

│   ├── 12737.bbbb.aaaa.30641

│   ├── 17032.bbbb.aaaa.5354

│   ├── 21081.bbbb.aaaa.3048

│   ├── 21756.bbbb.aaaa.8385

│   ├── 22604.bbbb.aaaa.5479

│   ├── 25455.bbbb.aaaa.15569

│   └── 908.bbbb.aaaa.6656

├── folder10

│   ├── 12278.bbbb.aaaa.24781

│   ├── 12531.bbbb.aaaa.18610

│   ├── 12553.bbbb.aaaa.26293

│   ├── 13986.bbbb.aaaa.21233

│   ├── 16762.bbbb.aaaa.28565

│   ├── 18204.bbbb.aaaa.3966

│   ├── 21641.bbbb.aaaa.32199

│   ├── 27439.bbbb.aaaa.5290

│   ├── 29034.bbbb.aaaa.27661

│   └── 8559.bbbb.aaaa.8375

├── folder2

│   ├── 12129.bbbb.aaaa.8577

│   ├── 13968.bbbb.aaaa.19321

│   ├── 14165.bbbb.aaaa.14814

│   ├── 14706.bbbb.aaaa.8526

│   ├── 24045.bbbb.aaaa.2795

│   ├── 24694.bbbb.aaaa.29560

│   ├── 27578.bbbb.aaaa.11558

│   ├── 31307.bbbb.aaaa.23101

│   ├── 6832.bbbb.aaaa.21816

│   └── 8623.bbbb.aaaa.31841

├── folder3

│   ├── 15083.bbbb.aaaa.20257

│   ├── 16040.bbbb.aaaa.17715

│   ├── 22351.bbbb.aaaa.4508

│   ├── 23943.bbbb.aaaa.31019

│   ├── 31148.bbbb.aaaa.18629

│   ├── 3986.bbbb.aaaa.28183

│   ├── 4512.bbbb.aaaa.10586

│   ├── 556.bbbb.aaaa.10129

│   ├── 6788.bbbb.aaaa.1529

│   └── 8083.bbbb.aaaa.6100

├── folder4

│   ├── 1489.bbbb.aaaa.1911

│   ├── 15176.bbbb.aaaa.32586

│   ├── 16175.bbbb.aaaa.9943

│   ├── 21008.bbbb.aaaa.19888

│   ├── 21119.bbbb.aaaa.13175

│   ├── 2392.bbbb.aaaa.6787

│   ├── 28505.bbbb.aaaa.29442

│   ├── 30897.bbbb.aaaa.27145

│   ├── 4206.bbbb.aaaa.18799

│   └── 8962.bbbb.aaaa.30663

├── folder5

│   ├── 10494.bbbb.aaaa.24576

│   ├── 14809.bbbb.aaaa.283

│   ├── 16862.bbbb.aaaa.22270

│   ├── 17580.bbbb.aaaa.8514

│   ├── 20989.bbbb.aaaa.14835

│   ├── 31812.bbbb.aaaa.22670

│   ├── 5834.bbbb.aaaa.26151

│   ├── 7242.bbbb.aaaa.28488

│   ├── 8160.bbbb.aaaa.22255

│   └── 8738.bbbb.aaaa.882

├── folder6

│   ├── 11308.bbbb.aaaa.13465

│   ├── 14302.bbbb.aaaa.29083

│   ├── 16917.bbbb.aaaa.11936

│   ├── 17604.bbbb.aaaa.9780

│   ├── 21554.bbbb.aaaa.16289

│   ├── 22798.bbbb.aaaa.17585

│   ├── 31556.bbbb.aaaa.20960

│   ├── 31857.bbbb.aaaa.5151

│   ├── 8647.bbbb.aaaa.15904

│   └── 9013.bbbb.aaaa.29253

├── folder7

│   ├── 10594.bbbb.aaaa.8776

│   ├── 11100.bbbb.aaaa.23506

│   ├── 11927.bbbb.aaaa.24818

│   ├── 13583.bbbb.aaaa.29967

│   ├── 14045.bbbb.aaaa.447

│   ├── 17428.bbbb.aaaa.32493

│   ├── 21599.bbbb.aaaa.18679

│   ├── 24784.bbbb.aaaa.14553

│   ├── 25158.bbbb.aaaa.1911

│   └── 26280.bbbb.aaaa.18213

├── folder8

│   ├── 15176.bbbb.aaaa.2173

│   ├── 19330.bbbb.aaaa.21758

│   ├── 21226.bbbb.aaaa.14602

│   ├── 24804.bbbb.aaaa.12936

│   ├── 28993.bbbb.aaaa.25644

│   ├── 30956.bbbb.aaaa.2067

│   ├── 3138.bbbb.aaaa.27010

│   ├── 6525.bbbb.aaaa.26555

│   ├── 7623.bbbb.aaaa.5494

│   └── 9646.bbbb.aaaa.17982

└── folder9

    ├── 17836.bbbb.aaaa.16299

    ├── 18434.bbbb.aaaa.389

    ├── 2123.bbbb.aaaa.10130

    ├── 21589.bbbb.aaaa.11375

    ├── 29964.bbbb.aaaa.5841

    ├── 31073.bbbb.aaaa.1026

    ├── 3974.bbbb.aaaa.25045

    ├── 409.bbbb.aaaa.7554

    ├── 4139.bbbb.aaaa.6583

    └── 5544.bbbb.aaaa.28749


10 directories, 100 files

kaka@debian:/tmp$

Działa :).

Jedyne co mi się w tym skrypcie nie podoba, to read. Na bank można to zrobić odnosząc się jako do tablicy, ale za cholerę nie mogę sobie przypomnieć jak to zapisać (a nie chce mi się szukać).


(Kaka') #3

Mać… Nie doczytałem do końca Twojego problemu. Może być wiele subkatalogów. Powyższe odnosi się tylko do jednego subkatalogu. Tutaj masz poprawioną wersję:

kaka@debian:/tmp$ cat new_make.sh 

#!/bin/bash


DIR=/tmp/areh2

const="aaaa"


for i in `seq 1 10`

do

    mkdir -p $DIR/folder$i

    for x in `seq 1 10`

    do

        mkdir -p $DIR/folder$i/folder$x

        touch $DIR/folder$i/$RANDOM.$const.$RANDOM

        for z in `seq 1 10`

        do

            touch $DIR/folder$i/folder$x/$RANDOM.$const.$RANDOM

        done

    done

done


kaka@debian:/tmp$

kaka@debian:/tmp$ cat ./new_skr.sh 

#!/bin/bash


DIR=/tmp/areh2

const="aaaa"

const_2="bbbb"


for i in `find $DIR -name "*$const*"`

do

    b=`basename $i`

    read zm_1 zm_2 <<< ${b//$const/ }

    mv $i `dirname $i`/"$zm_1""$const_2"."$const""$zm_2"

done

kaka@debian:/tmp$

W przypadku wielu podkatalogów, również można użyć for’a rekurencyjnie, ale chyba prościej (i czytelniej) to zapisać find’em. Nowa wersja jest z find’em. Spróbuj sobie zrobić to for’em, tak dla ćwiczenia :). Nie wstawiam tutaj już listingu z przed i po wykonaniu skryptu, bo za wiele by zajmował. Możesz sobie zrzucić wyniki do pliku i zrobić diff’a, np.:

./new_make.sh

tree /tmp/areh2 > file_make

./new_skr.sh

tree /tmp/areh2 > file_skr

meld file_make file_skr

PS: nie bijcie za kod, jest już późno, w pracy dostatecznie dużo kodziłem, a teraz jeszcze tutaj mi się zachciało :P.


#4

Jak zawsze nieoceniony kaka’ :D.

Chyba jednak mało konkretnie opisałem problem w pierwszym poście. Te zmienne o których pisałem to są już konkretne ciągi znaków, które po zmianie muszą zostać takie same (coś podobnego do tego w czym mi ostatnio pomagałeś). Te stałe z kolei, to stały ciąg znaków, który we wszystkich plikach jest identyczny.

Spróbuję coś sam pokodzić na podstawie tego co zrobiłeś, ale nie wiem jaki będzie tego skutek :D.

W każdym bądź razie dzięki za pomoc.


(Kaka') #5

Stałe są zachowane - zrób sobie diffa tak jak pokazałem (meld jest fajny i prosty). Ja po prostu wygenerowałem przykładowe nazwy za pomocą $RANDOM (no sorry, ale nie będę z palca wymyślać chociażby 100 nazw :P). Spójrz w diff - wszystko będzie jasne.

Co do stałej, którą podałeś… Skoro zawsze jest taka sama, to przecież możesz ją wbić na sztywno w skrypt (tak jak ja to zrobiłem - $const). Tak samo druga stała. Na upartego, bardziej uniwersalnie, możesz wyciągnąć stałą z jakiegokolwiek pliku (z jego nazwy), przykładowo tak jak zrobiłem read. Ale jaki jest tego sens? Skoro wyciągasz z nazwy, logiczne jest, że nie jesteś pewien wartości tej stałej - tym samym, nie możesz tej wartości nazwać stałą :).


#6

Sorki, po pracy jestem, zmęczenie daje znać o sobie. Popatrzyłem najpierw na jeden skrypt, później na drugi, nie wiem dlaczego wydawało mi się że to jeden i ten sam :smiley:


EDIT

Zacząłem to robić trochę innych sposobem. Żeby zachować te “zmienne” zrobiłem to tak:

new_name="`echo $i | cut -d '.' -f 1`.stała0.stała.[zmienna2]"

Właściwie to nie do końca zrobiłem, bo nie mogę rozgryźć tego co powinienem wstawić w miejsce [zmienna2]. Czytałem man cut, ale nie bardzo mi to wychodzi. Nie napisałem tego chyba w pierwszym poście: zmienna1 i zmienna2 przed zmianą i po zmianie nazwy pliku nie mogą się zmienić.


(Kaka') #7

Areh, przecież moje przykładowe skrypty zachowują stałe…


#8

Tak, wiem, ale ja kombinuję jak to zrobić też na inny sposób, z wykorzystaniem właśnie cut.

Dodane 12.08.2013 (Pn) 19:44

Zrobiłem to moim zdaniem szybszym sposobem, może kumuś się przyda:

new_name="`echo $i | cut -d '.' -f 1`.stała0.stała.`echo $i | rev | cut -d '.' -f 1 | rev`"\