Jak mogę użyć zmiany nazwy, aby rekurencyjnie zmienić nazwę każdego na wielkie litery

11

Chciałbym rekurencyjnie zmieniać nazwy wszystkich plików i folderów (podfolderów) na wielkie litery.

Znalazłem kilka skryptów, które zrobią to małymi literami, ale nie wiem, jak je zmienić, więc zrobi to na odwrót (od dolnej do górnej).

Skrypt, który znalazłem i działa na małe litery, ale nie wiedziałem, jak go zmienić, to:

rename 'y/A-Z/a-z/' *

To jest z man rename.

jnhghy - Alexandru Jantea
źródło
Nie wiedząc nic o poleceniu zmiany nazwy, podejrzewam, że jeśli spróbujesz rename 'y/a-z/A-Z/' *, dostaniesz to, czego chcesz. Ostrożnie tam, gdzie to przetestujesz.
Warwick,
nie jest to powtarzalne (ponieważ początkowa nie była ...), ale działa. Nie rozumiem, dlaczego nie myślałem o tym nieszczęściu :), dzięki!
jnhghy - Alexandru Jantea
Myślę, że biorąc pod uwagę jakość odpowiedzi Gillesa, byłoby dobrze, gdybyś zaakceptował jego odpowiedź zamiast mojej. Jest o wiele bardziej kompletny niż mój i wyjaśnia twoje opcje (i jak to wszystko działa). Dzięki.
Warwick

Odpowiedzi:

8

Zauważ, że używasz skryptu Perla zwanegorename dystrybuowanym przez Debian i jego pochodne (Ubuntu, Mint,…). Inne dystrybucje Linuksa zawierają zupełnie inną i znacznie mniej użyteczną komendę o nazwie rename.

y/A-Z/a-z/tłumaczy każdy znak w zakresie Apoprzez Zdo odpowiedniego znaku w zakresie apoprzez z, czyli ASCII wielkich liter do odpowiedniej litery małe. Aby wykonać odwrotne tłumaczenie, użyj y/a-z/A-Z/. Innym sposobem, aby napisać to samo polecenie rename '$_ = uc($_)' *ucjest u pper c funkcja ASE, a renamekomenda zmienia nazwy plików na podstawie przekształceń dokonanych w $_zmiennej.

rename '…' *zmienia tylko nazwy plików w bieżącym katalogu, ponieważ to właśnie *pasuje. Pliki kropkowe (pliki, których nazwa zaczyna się na .) są również pomijane.

Jeśli chcesz zmieniać nazwy plików w bieżącym katalogu i podkatalogach rekurencyjnie, możesz użyć findpolecenia, aby rekurencyjnie przechodzić do bieżącego katalogu. Jest tu trudność: jeśli zadzwonisz rename, to zmieni nazwę zarówno katalogu, jak i nazwy podstawowej. Jeśli wywołujesz renamekatalog przed rekursowaniem w nim ( find -exec rename … {} \;), findstaje się zdezorientowany, ponieważ znalazł katalog, ale katalog ten już nie istnieje, dopóki nie spróbuje w niego zejść. Można to obejść mówiąc findprzemierzać katalogu przed działających na nim, ale potem kończy się próbą zmiany nazwy foo/barna FOO/BARale katalog FOOnie istnieje.

Prostym sposobem na uniknięcie tej trudności jest spowodowanie, aby polecenie zmiany nazwy działało tylko na nazwę podstawową na ścieżce. Wyrażenie regularne ([^/]*\Z)pasuje do końcowej części ścieżki, która nie zawiera /.

find . -depth -exec rename 's!([^/]*\Z)!uc($1)!e' {} +

Powłoka Zsh zapewnia wygodniejsze funkcje zmiany nazwy - nawet bardziej tajemnicze niż Perl, ale bardziej rozbudowane i często łatwiejsze do skomponowania.

Funkcja zmvzmienia nazwy plików na podstawie wzorców. Uruchom autoload -U zmvraz, aby go aktywować (wstaw tę linię do swojego .zshrc).

W pierwszym argumencie do zmv(wzorzec do zastąpienia) możesz użyć potężnych wzorców symboli wieloznacznych zsh . W drugim argumencie do zmv(tekst zastępczy) możesz użyć funkcji rozszerzania parametrów , w tym modyfikatorów historii .

zmv -w '**/*' '$1$2:u'

Wyjaśnienie:

  • -w - automatyczne przypisywanie zmiennych numerycznych do każdego wzoru wieloznacznego
  • **/*- wszystkie pliki w podkatalogach, rekurencyjnie ( **/dopasowuje 0, 1 lub więcej poziomów podkatalogów)
  • $1 - pierwsza zmienna numeryczna, tutaj pasująca do części katalogowej każdej ścieżki
  • $2:u- druga zmienna liczbowa, tutaj pasująca do podstawowej nazwy części każdej ścieżki, z :umodyfikatorem do konwersji wartości na wielkie litery

Dodatkową korzyścią jest przestrzeganie ustawień regionalnych otoczenia.

Jeśli nie masz pewności, co do zmvpolecenia, które napisałeś, możesz przekazać -nopcję wydrukowania tego, co zrobi polecenie, i niczego nie zmieniać. Sprawdź dane wyjściowe, a jeśli zrobi to, co chcesz, ponownie uruchom komendę bez -nfaktycznego działania.

Gilles „SO- przestań być zły”
źródło
5

Skradziony (z niewielką zmianą) z posta Gillesa tutaj

find <DIR> -depth -type d -exec rename -n 's!/([^/]*/?)$!\U/$1!' {} +

Warwick
źródło
To nie działa rekurencyjnie.
Gilles 'SO - przestań być zły'
Prawdziwe. Powinienem był poprawnie przeczytać pytanie. Nie mam dostępu do polecenia zmiany nazwy, ale wierzę, że zadziała to rekurencyjnie -find <dir> -exec rename 'y/a-z/A-Z/' {} \;
Warwick
Jest to nieco bardziej skomplikowane, ponieważ zmieniasz nazwy katalogów, gdy findsię do nich rekursuje.
Gilles „SO- przestań być zły”
@Gilles - OK. Po przeprowadzeniu drobnych badań wydaje się, że muszę dodać opcję -depth, aby znaleźć, aby nazwy katalogów były obsługiwane na końcu. find <dir> -depth -exec rename 'y/a-z/A-Z/' {} \;Powinien więc poradzić sobie z problemem zmiany nazw katalogów. Poprawny?
Warwick,
Nie, to wciąż nie działa, ponieważ renamezmiany np. foo/barDo FOO/BARi FOOnie istnieją w tym momencie.
Gilles 'SO - przestań być zły'
2

Chciałbym skierować każdego, kto nadal jest powiązany z tą odpowiedzią, na doskonałą odpowiedź, którą Guiles Quernot udzielił na to pytanie, które nie wymaga find.

Wynikowe polecenie to:

shopt -s globstar
rename -n 'y/a-z/A-Z/' **

Ale przed uruchomieniem przeczytaj odpowiedź połączoną z zastrzeżeniami dotyczącymi starych wersji bash.

Wreszcie, jeśli ktoś zastanawia się, co robi y///polecenie perl regex. Oto link do odpowiedniej dokumentacji .

Marcelo Lacerda
źródło
1

find -execdir| Przemianować

Byłby to najlepszy sposób, aby to zrobić, gdyby nie względne szaleństwo ścieżki, ponieważ pozwala uniknąć perlowego wyrażenia regularnego, aby działało tylko na basenieame:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find a -depth -execdir rename 's/(.*)/\U$1/' '{}' \;

-execdirnajpierw cds do katalogu przed wykonaniem tylko na basenieame.

Niestety nie mogę pozbyć się tej PATHczęści hakowania, find -execdirodmawia zrobienia czegokolwiek, jeśli masz względną ścieżkę w PATH...: /ubuntu/621132/why-using-the-execdir-action- is-niepewne-dla-katalogu-który-jest-na-ścieżce / 1109378 # 1109378

Ciro Santilli
źródło
0

Spróbuj tego po przejściu do katalogu, w którym chcesz zmienić nazwę plików:

for word in `ls -ltr |tail -n +2 |awk '{print $9}'`
do
  a=$(echo $word | tr '[a-z]' '[A-Z]')
  mv $word $a
  echo "Done Successfully"
done
Sorav
źródło
Nie analizuj danych wyjściowych ls (i dlaczego, u licha, miałbyś biegać ls -ltylko po to, aby odciąć kolumny inne niż nazwa?) I stosuj podwójne cudzysłowy wokół podstawień zmiennych . Twój kod jest zbyt skomplikowany i łamie nazwy plików zawierające białe znaki i inne znaki specjalne. Użyj findlub, **/aby przejść do podkatalogów, dane wyjściowe lssą przeznaczone wyłącznie do spożycia przez ludzi.
Gilles 'SO - przestań być zły'