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
.
rename 'y/a-z/A-Z/' *
, dostaniesz to, czego chcesz. Ostrożnie tam, gdzie to przetestujesz.Odpowiedzi:
Zauważ, że używasz skryptu Perla zwanego
rename
dystrybuowanym przez Debian i jego pochodne (Ubuntu, Mint,…). Inne dystrybucje Linuksa zawierają zupełnie inną i znacznie mniej użyteczną komendę o nazwierename
.y/A-Z/a-z/
tłumaczy każdy znak w zakresieA
poprzezZ
do odpowiedniego znaku w zakresiea
poprzezz
, czyli ASCII wielkich liter do odpowiedniej litery małe. Aby wykonać odwrotne tłumaczenie, użyjy/a-z/A-Z/
. Innym sposobem, aby napisać to samo polecenierename '$_ = uc($_)' *
-uc
jest u pper c funkcja ASE, arename
komenda 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ć
find
polecenia, aby rekurencyjnie przechodzić do bieżącego katalogu. Jest tu trudność: jeśli zadzwoniszrename
, to zmieni nazwę zarówno katalogu, jak i nazwy podstawowej. Jeśli wywołujeszrename
katalog przed rekursowaniem w nim (find -exec rename … {} \;
),find
staje 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ącfind
przemierzać katalogu przed działających na nim, ale potem kończy się próbą zmiany nazwyfoo/bar
naFOO/BAR
ale katalogFOO
nie 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/
.Powłoka Zsh zapewnia wygodniejsze funkcje zmiany nazwy - nawet bardziej tajemnicze niż Perl, ale bardziej rozbudowane i często łatwiejsze do skomponowania.
Funkcja
zmv
zmienia nazwy plików na podstawie wzorców. Uruchomautoload -U zmv
raz, 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 dozmv
(tekst zastępczy) możesz użyć funkcji rozszerzania parametrów , w tym modyfikatorów historii .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:u
modyfikatorem do konwersji wartości na wielkie literyDodatkową korzyścią jest przestrzeganie ustawień regionalnych otoczenia.
Jeśli nie masz pewności, co do
zmv
polecenia, które napisałeś, możesz przekazać-n
opcję wydrukowania tego, co zrobi polecenie, i niczego nie zmieniać. Sprawdź dane wyjściowe, a jeśli zrobi to, co chcesz, ponownie uruchom komendę bez-n
faktycznego działania.źródło
Skradziony (z niewielką zmianą) z posta Gillesa tutaj
find <DIR> -depth -type d -exec rename -n 's!/([^/]*/?)$!\U/$1!' {} +
źródło
find <dir> -exec rename 'y/a-z/A-Z/' {} \;
find
się do nich rekursuje.find <dir> -depth -exec rename 'y/a-z/A-Z/' {} \;
Powinien więc poradzić sobie z problemem zmiany nazw katalogów. Poprawny?rename
zmiany np.foo/bar
DoFOO/BAR
iFOO
nie istnieją w tym momencie.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:
Ale przed uruchomieniem przeczytaj odpowiedź połączoną z zastrzeżeniami dotyczącymi starych wersji bash.
Wreszcie, jeśli ktoś zastanawia się, co robi
y///
polecenieperl regex
. Oto link do odpowiedniej dokumentacji .źródło
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:
-execdir
najpierwcd
s do katalogu przed wykonaniem tylko na basenieame.Niestety nie mogę pozbyć się tej
PATH
części hakowania,find -execdir
odmawia zrobienia czegokolwiek, jeśli masz względną ścieżkę wPATH
...: /ubuntu/621132/why-using-the-execdir-action- is-niepewne-dla-katalogu-który-jest-na-ścieżce / 1109378 # 1109378źródło
Spróbuj tego po przejściu do katalogu, w którym chcesz zmienić nazwę plików:
źródło
ls -l
tylko 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żyjfind
lub,**/
aby przejść do podkatalogów, dane wyjściowels
są przeznaczone wyłącznie do spożycia przez ludzi.