Jak zmienić nazwy wszystkich folderów i plików na małe litery w systemie Linux?

179

Muszę rekurencyjnie zmienić nazwę całego drzewa folderów, aby nigdzie nie pojawiała się żadna wielka litera (jest to kod źródłowy C ++, ale to nie powinno mieć znaczenia).

Dodatkowe punkty za ignorowanie plików / folderów kontroli wersji CVS i Subversion. Preferowanym sposobem byłby skrypt powłoki, ponieważ powłoka powinna być dostępna na każdym Linuksie.

Pojawiło się kilka ważnych argumentów dotyczących szczegółów zmiany nazwy pliku.

  1. Myślę, że pliki z tymi samymi małymi literami powinny zostać nadpisane; to problem użytkownika. Po wyewidencjonowaniu w systemie plików z ignorowaniem wielkości liter, nadpisze pierwszy również drugim.

  2. Rozważyłbym znaki AZ i przekształciłbym je w az, wszystko inne po prostu wywołuje problemy (przynajmniej z kodem źródłowym).

  3. Skrypt byłby potrzebny do uruchomienia kompilacji w systemie Linux, więc myślę, że zmiany w plikach kontroli wersji CVS lub Subversion powinny zostać pominięte. W końcu to tylko zwykła kasa. Może bardziej odpowiedni jest „eksport”.

vividos
źródło
Opublikowane wcześniej będzie działać idealnie po wyjęciu z pudełka lub z kilkoma poprawkami dla prostych przypadków, ale są pewne sytuacje, które warto wziąć pod uwagę przed uruchomieniem zmiany nazwy partii: 1. Co powinno się stać, jeśli masz dwie lub więcej nazw w tym samym poziomie hierarchii drogi, która różni się jedynie od przypadku, na przykład ABCdef, abcDEFi aBcDeF? Czy skrypt zmiany nazwy powinien przerwać, czy po prostu ostrzec i kontynuować? 2. Jak definiuje się małe litery w nazwach innych niż US-ASCII? Jeśli takie nazwiska mogą być obecne, czy należy najpierw sprawdzić i wykluczyć zaliczenie? 3. Jeśli prowadzisz operację zmiany nazwy
Mihai Limbășan

Odpowiedzi:

179

Zwięzła wersja za pomocą "rename"polecenia:

find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

Pozwala to uniknąć problemów ze zmianą nazw katalogów przed plikami i próbą przeniesienia plików do nieistniejących katalogów (np. "A/A"Do "a/a").

Lub bardziej szczegółową wersję bez użycia "rename".

for SRC in `find my_root_dir -depth`
do
    DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'`
    if [ "${SRC}" != "${DST}" ]
    then
        [ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
    fi
done

PS

Ta ostatnia zapewnia większą elastyczność dzięki poleceniu ruchu (na przykład "svn mv").

Alex B.
źródło
36
za pomocą funkcji rename można również zmienić nazwę 'y / AZ / az /' *
Tzury Bar Yochay
3
Uwaga, obie wersje nie będą działać na systemie plików bez rozróżniania wielkości liter. W moim przypadku zamieniłem thenlinię zamkniętą na (mv "${SRC}" "${DST}.renametmp" && mv "${DST}.renametmp" "${DST}") || echo "${SRC} was not renamed".
Lloeki
6
Drugie podejście nie działało poprawnie dla mnie z plikami zawierającymi spacje (kontekst: linux, bash).
przyciemniony
4
Używając ostatniej wersji zmiany nazwy, nie jest potrzebne żadne wyrażenie regularne. Pełne polecenie staje się find my_root_dir -depth -exec rename -c {} \;. Dodaj -f do zmiany nazwy, jeśli jesteś na systemie plików bez uwzględniania wielkości liter (np Mac)
Javache
Drugi działał dla mnie na Solarisie, usuwając -Tz mvpolecenia.
Szynka,
261

Jeszcze mniejszy lubię:

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

W systemach plików niewrażliwych na wielkość liter, takich jak HFS + w OS X , będziesz chciał dodać -fflagę:

rename -f 'y/A-Z/a-z/' *
tristanbailey
źródło
3
linux.icydog.net/rename.php :The renaming utility that comes by default with Ubuntu is a Perl program sometimes called prename
sleepsort
1
Dzięki, użyłem go w ten sposób $ find | xargs zmienia nazwę na 'y / AZ / az /' *
Rashi
5
Zakłada się, że masz zmianę nazwy perlów, co nie zawsze ma miejsce. np. na moim debianie zmiana nazwy jest zupełnie inna
Krzysztof Krasoń
10
Na Arch program jest wywoływany perl-rename(i jest dostarczany przez pakiet o tej samej nazwie)
jaymmer - Przywróć Monikę
3
To nie rozwiązuje podanego problemu, ponieważ „zmiana nazwy” nie jest rekurencyjna.
Cybolic
89
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
Swaroop CH
źródło
Przed uruchomieniem skryptu wykonaj polecenie „mkdir -p A / B / C”.
tzot
2
„find” należy zastąpić jakimkolwiek poleceniem, którego używasz do uzyskania listy plików, których nazwę chcesz zmienić; na przykład „ls *. {C, CPP, H}”.
JPaget
2
Nie działa na OS X, po prostu drukuje informacje o użytkowaniu find. find .wydaje się to naprawić.
emlai
3
Wersja „skonsolidowana”, ze wszystkich komentarzy (odpowiedzi nie można już edytować):for f in `find .`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
romaricdrigon
1
Czy ktoś może mi wyjaśnić, dlaczego to powinno działać w pierwszej kolejności? Jeśli znajdzie ./FOO i ./FOO/BAR, najpierw zmienia nazwę ./FOO na ./foo, po czym nie może już znaleźć ./FOO/BAR. Wprowadzenie własnej odpowiedzi poniżej powinno rozwiązać ten problem.
oisyn
80

Po prostu wypróbuj poniższe, jeśli nie musisz dbać o wydajność.

zip -r foo.zip foo/*
unzip -LL foo.zip
Ginhing
źródło
13
Wow, to dość nieefektywny sposób.
Artjom B.
28
Zakładając, że wydajność obliczeniowa zwykle NIE jest problemem, gdy musisz zmienić nazwy plików w katalogu ... Myślę, że jest to prawdopodobnie najbardziej twórcze rozwiązanie w tym wątku. Naprawdę coś tak trywialnego nie powinno być tak skomplikowane, jak pokazują przyjęte odpowiedzi, a to obejście jest znacznie bardziej proporcjonalne do ilości myśli, jaką chcę zainwestować w taką operację. +1000
Peter M. Elias
27
Można ją przyspieszyć z -0(to „zero”, bez kompresji) przełącznik zip -0 -r foo.zip foo/.
Johnny Baloney
3
Musiałem zmienić ponad 50 000 nazw plików w różnych strukturach katalogów. Oryginalna, zaakceptowana odpowiedź wykonała zaledwie 10% pracy w 2 minuty, podczas gdy -0kompresja była prawie natychmiastowa!
Peon
2
To nie tylko nieefektywne. To jest po prostu niemożliwe, jeśli nie ma wystarczającej ilości wolnego miejsca na tymczasowe archiwum.
Victor Yarema,
19

Człowieku, wy chłopaki / dziewczyny lubicie zbytnio komplikować rzeczy ...

rename 'y/A-Z/a-z/' *
Stephen
źródło
2
To nie działa, mówi, że plik z nazwą z małą literą już istnieje.
kirhgoff
@kirhgoff Widziałem, że dzieje się tak z montowaniami NFS - postępuj zgodnie z instrukcjami tutaj .
joebeeson
Jak możemy zmienić nazwę w systemie plików uwzględniającym wielkość liter? rename 'y/a-z/A-Z/' /tmp/*.jpg-> Can't rename /tmp/*.jpg /TMP/*.JPG: No such file or directory, czyli spróbuj zmienić nazwę całej ścieżki zamiast tylko pliku.
Pablo A
14

Większość powyższych odpowiedzi jest niebezpieczna, ponieważ nie dotyczą nazw zawierających dziwne znaki. Twój najbezpieczniejszym dla tego rodzaju rzeczą jest użycie find„s -print0opcję, która będzie rozwiązać nazwy plików z ASCII NUL zamiast \ n.

Oto skrypt, który zmienia tylko pliki, a nie nazwy katalogów, aby nie pomylić find:

find .  -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "$0")/$(basename "$0");
d=$(dirname "$0")/$(basename "$0"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'

Przetestowałem to i działa z nazwami plików zawierającymi spacje, wszelkiego rodzaju cudzysłowy itp. Jest to ważne, ponieważ jeśli uruchamiasz jako root jeden z tych innych skryptów na drzewie, które zawiera plik utworzony przez

touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash

... Zastanów się ...

niXar
źródło
Byłoby prostsze w użyciu renamezamiast mv.
Victor Yarema,
14

Działa to, jeśli masz już lub skonfigurowałeś polecenie zmiany nazwy (np. Poprzez instalację brew na Macu):

rename --lower-case --force somedir/*
alemol
źródło
9
... jeśli najpierw ustawisz zmianę nazwy, np. przezbrew install rename
pduersteler
3
zmień nazwę 'y / AZ / az /' *
Stephen
4
--lower-case? Tak nie jest, przynajmniej niestety w Arch Linux.
3
renamenie jest wbudowanym bashem. Jest to narzędzie zewnętrzne, którego składnia będzie się różnić w zależności od zainstalowanej wersji. Ta odpowiedź nie jest wystarczająca jako przenośne rozwiązanie „dla wszystkich systemów operacyjnych opartych na unixie”, jak twierdzono.
Corey Goldberg,
2
Właśnie zaznaczone, renamepolecenie zawarte w najnowszej Fedorze (28), za pośrednictwem util-linux-2.31pakietu, nie ma --lower-caseopcji.
niXar
11

Działa to na CentOS / Red Hat Linux lub innych dystrybucjach bez renameskryptu Perl:

for i in $( ls | grep [A-Z] ); do mv -i "$i" "`echo $i | tr 'A-Z' 'a-z'`"; done

Źródło: zmień nazwy wszystkich plików z wielkich na małe litery

(W niektórych dystrybucjach domyślne renamepolecenie pochodzi z util-linux i jest to inne, niekompatybilne narzędzie).

Pere
źródło
Działa to tylko na jednym katalogu, a nie rekurencyjnie
Bram
Coool .. Działa dobrze
Manikandan Ram
6

Najprostszym podejściem, które znalazłem w systemie Mac OS X, było użycie pakietu zmiany nazwy z http://plasmasturm.org/code/rename/ :

brew install rename
rename --force --lower-case --nows *

--force Zmień nazwę, nawet jeśli plik o nazwie docelowej już istnieje.

--lower-case Konwertuje nazwy plików na wszystkie małe litery.

--nows Zamienia wszystkie sekwencje białych znaków w nazwie pliku na pojedyncze znaki podkreślenia.

Kim T.
źródło
5

Oto moje nieoptymalne rozwiązanie, używając skryptu powłoki Bash:

#!/bin/bash
# First, rename all folders
for f in `find . -depth ! -name CVS -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming folder $f"
      mv -f "$f" "$g"
   fi
done

# Now, rename all files
for f in `find . ! -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming file $f"
      mv -f "$f" "$g"
   fi
done

Wszystkie foldery mają poprawne nazwy, a mv nie zadają pytań, gdy uprawnienia się nie zgadzają, a nazwy folderów CVS nie są zmieniane (nazwy plików kontrolnych CVS w tym folderze są niestety nadal zmieniane).

Ponieważ "find -depth" i "find | sort -r" zwracają listę folderów w możliwej do zmiany kolejności kolejności, wolałem używać "-depth" do wyszukiwania folderów.

vividos
źródło
Twoje pierwsze znalezisko nie działa. Spróbuj „mkdir -p A / B / C”, a następnie uruchom skrypt.
tzot
4

Pierwotne pytanie dotyczyło ignorowania katalogów SVN i CVS, co można zrobić, dodając -prune do polecenia find. Np. Aby zignorować CVS:

find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print

[edytuj] Wypróbowałem to i osadzenie tłumaczenia pisanego małymi literami wewnątrz znaleziska nie działało z powodów, których właściwie nie rozumiem. Więc zmień to, aby:

$> cat > tolower
#!/bin/bash
mv $1 `echo $1 | tr '[:upper:]' '[:lower:]'`
^D
$> chmod u+x tolower 
$> find . -name CVS -prune -o -exec tolower '{}'  \;

Ian

Ian Dickinson
źródło
4

Korzystanie z narzędzia do naprawy nazw plików Larry'ego Walla:

$op = shift or die $help;
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

To jest tak proste, jak

find | fix 'tr/A-Z/a-z/'

(gdzie fixjest oczywiście powyższy skrypt)

agnul
źródło
3

To jest mały skrypt powłoki, który robi to, o co prosiłeś:

root_directory="${1?-please specify parent directory}"
do_it () {
    awk '{ lc= tolower($0); if (lc != $0) print "mv \""  $0 "\" \"" lc "\"" }' | sh
}
# first the folders
find "$root_directory" -depth -type d | do_it
find "$root_directory" ! -type d | do_it

Zwróć uwagę na akcję -depth w pierwszym znalezieniu.

tzot
źródło
1
Jedyna rzecz, która działała na Macu z całego wątku. Dzięki!
YemSalat
2

Nie przenośny, tylko Zsh, ale dość zwięzły.

Najpierw upewnij się, że zmvjest załadowany.

autoload -U zmv

Upewnij się też, że extendedglobjest włączony:

setopt extendedglob

Następnie użyj:

zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}'

Do plików i katalogów zapisywanych małymi literami, których nazwa nie jest CVS .

benjwadams
źródło
2
for f in `find -depth`; do mv ${f} ${f,,} ; done

find -depthdrukuje każdy plik i katalog, z zawartością katalogu wypisywaną przed samym katalogiem. ${f,,}małe litery nazwy pliku.

Chris Schierkolk
źródło
To nie działa: zmienia nazwę katalogu, zanim zacznie operować na zawartości, tak że późniejsza próba na zawartości nie powiedzie się.
Prune
Dodanie -depthpoprawki! To naprawdę szybkie rozwiązanie, ale oczywiście bez korzystania z -print0opcji wyszukiwania nie jest najbardziej niezawodne
jpaugh
@jpaugh Nie, nie ma. Spróbuje zmienić nazwę ./FOO/BAR na ./foo/bar, ale ./foo jeszcze nie istnieje.
oisyn
2

W systemie MacOS

Zainstaluj renamepakiet,

brew install rename

Posługiwać się,

find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"                       

To polecenie znajduje wszystkie pliki z *.pyrozszerzeniem i konwertuje nazwy plików na małe litery.

`f` - forces a rename

Na przykład,

$ find . -iname "*.py" -type f
./sample/Sample_File.py
./sample_file.py
$ find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"
$ find . -iname "*.py" -type f
./sample/sample_file.py
./sample_file.py
akilesh raj
źródło
Dlaczego -Iużyłeś xargstutaj opcji ?
Victor Yarema,
- IFlaga nie jest obowiązkowe. Jest używany, gdy wykonujemy wiele poleceń z xargs. Oto przykład użycia wielu poleceń w programie xargs cat foo.txt | xargs -I % sh -c 'echo %; mkdir %' Możesz uruchomić bez -Ipodobnychfind . -iname "*.py" -type f | xargs -I% rename -c -f "%"
akilesh raj
2

Użyj składu :

typeset -l new        # Always lowercase
find $topPoint |      # Not using xargs to make this more readable
  while read old
  do new="$old"       # $new is a lowercase version of $old
     mv "$old" "$new" # Quotes for those annoying embedded spaces
  done

W systemie Windows emulacje, takie jak Git Bash , mogą zawieść, ponieważ system Windows nie rozróżnia wielkości liter pod maską. W tym celu dodaj krok, który mvjest plikiem, najpierw do innej nazwy, np. „$ Old.tmp”, a następnie do $new.

Paul Hodges
źródło
1

Długi, ale „Działa bez niespodzianek i instalacji”

Ten skrypt obsługuje nazwy plików ze spacjami, cudzysłowami, innymi nietypowymi znakami i Unicode, działa na systemach plików niewrażliwych na wielkość liter i większości środowisk Unix-y, które mają zainstalowane bash i awk (tj. Prawie wszystkie). Zgłasza również ewentualne kolizje (pozostawiając nazwę pliku wielkimi literami) i oczywiście zmienia nazwy zarówno plików i katalogów, jak i działa rekurencyjnie. Wreszcie jest wysoce adaptowalny: możesz dostosować polecenie find, aby wskazywało na pliki / katalogi, które chcesz, i możesz dostosować awk, aby wykonywać inne operacje na nazwach. Zauważ, że przez „obsługuje Unicode” mam na myśli, że rzeczywiście skonwertuje ich wielkość liter (nie ignoruj ​​ich jak odpowiedzi, które używają tr).

# adapt the following command _IF_ you want to deal with specific files/dirs
find . -depth -mindepth 1 -exec bash -c '
  for file do
    # adapt the awk command if you wish to rename to something other than lowercase
    newname=$(dirname "$file")/$(basename "$file" | awk "{print tolower(\$0)}")
    if [ "$file" != "$newname" ] ; then
        # the extra step with the temp filename is for case-insensitive filesystems
        if [ ! -e "$newname" ] && [ ! -e "$newname.lcrnm.tmp" ] ; then
           mv -T "$file" "$newname.lcrnm.tmp" && mv -T "$newname.lcrnm.tmp" "$newname" 
        else
           echo "ERROR: Name already exists: $newname"
        fi
    fi    
  done
' sh {} +

Bibliografia

Mój skrypt oparty jest na tych doskonałych odpowiedziach:

/unix/9496/looping-through-files-with-spaces-in-the-names

Jak przekonwertować ciąg na małe litery w Bash?

ndemou
źródło
1

Działa to również dobrze na macOS:

ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
Chris
źródło
Jest to szczególnie przyjemne, ponieważ Ruby jest dostarczany z systemem macOS.
jxmorris12
1

Musiałem to zrobić w konfiguracji Cygwin w systemie Windows 7 i stwierdziłem, że mam błędy składniowe z sugestiami z góry, które próbowałem (chociaż mogłem przegapić działającą opcję). Jednak to rozwiązanie prosto z forów Ubuntu wyszło z puszki :-)

ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done

(Uwaga: wcześniej zastępowałem białe spacje podkreśleniami, używając:

for f in *\ *; do mv "$f" "${f// /_}"; done

)

jacanterbury
źródło
1

W OS X mv -fpokazuje błąd „ten sam plik”, więc dwukrotnie zmieniam nazwę:

for i in `find . -name "*" -type f |grep -e "[A-Z]"`; do j=`echo $i | tr '[A-Z]' '[a-z]' | sed s/\-1$//`; mv $i $i-1; mv $i-1 $j; done
Jonghee Park
źródło
1

W takiej sytuacji sięgnąłbym po Pythona, aby uniknąć optymistycznego zakładania ścieżek bez spacji i ukośników. Zauważyłem również, że python2zwykle jest instalowany w większej liczbie miejsc niż rename.

#!/usr/bin/env python2
import sys, os

def rename_dir(directory):
  print('DEBUG: rename('+directory+')')

  # Rename current directory if needed
  os.rename(directory, directory.lower())
  directory = directory.lower()

  # Rename children
  for fn in os.listdir(directory):
    path = os.path.join(directory, fn)
    os.rename(path, path.lower())
    path = path.lower()

    # Rename children within, if this child is a directory
    if os.path.isdir(path):
        rename_dir(path)

# Run program, using the first argument passed to this Python script as the name of the folder
rename_dir(sys.argv[1])
John Foley
źródło
Porozmawiaj o tym, jak to skomplikować… po prostu zrób… zmień nazwę „y / AZ / az /” *
Stephen
1
@Stephen, przy założeniu, że masz uprawnienia administratora do instalacji zmiany nazwy. Często muszę zbierać dane o systemach, na których nie mam możliwości zainstalowania innego oprogramowania. W ostatnim Ubuntusie jest to instalowane tylko wtedy, gdy obecny jest perl.
John Foley,
1

Jeśli używasz Arch Linux , możesz zainstalować renamepakiet) z, AURktóry zawiera renamexmpolecenie jako /usr/bin/renamexmplik wykonywalny i stronę podręcznika wraz z nim.

To naprawdę potężne narzędzie do szybkiej zmiany nazw plików i katalogów.

Konwertuj na małe litery

rename -l Developers.mp3 # or --lowcase

Konwertuj na WIELKIE litery

rename -u developers.mp3 # or --upcase, long option

Inne opcje

-R --recursive # directory and its children

-t --test # Dry run, output but don't rename

-o --owner # Change file owner as well to user specified

-v --verbose # Output what file is renamed and its new name

-s/str/str2 # Substitute string on pattern

--yes # Confirm all actions

W razie potrzeby możesz pobrać przykładowy plik Developers.mp3 stąd ;)

Peter Mortensen
źródło
1
zmiana nazwy z brewna MacOS -lwiąże się z utworzeniem dowiązania symbolicznego i -ckonwersją na małe litery, więc uważaj.
rien333
0
( find YOURDIR -type d | sort -r;
  find yourdir -type f ) |
grep -v /CVS | grep -v /SVN |
while read f; do mv -v $f `echo $f | tr '[A-Z]' '[a-z]'`; done

Najpierw zmień nazwy katalogów od dołu do góry, sort -r (gdzie -depth nie jest dostępne), a następnie pliki. Następnie grep -v / CVS zamiast find ...- prune, ponieważ jest prostsze. W przypadku dużych katalogów f in ... może spowodować przepełnienie niektórych buforów powłoki. Użyj znajdź ... | podczas czytania aby tego uniknąć.

I tak, spowoduje to zbijanie plików, które różnią się tylko w przypadku ...

pklausner
źródło
Po pierwsze: find YOURDIR -type d | sort -rto zbyt duży problem. Chcesz find YOURDIR -depth -type d. Po drugie, find -type fMUSI zostać uruchomione po zmianie nazw katalogów.
tzot
0
find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'|sh

Nie próbowałem bardziej rozbudowanych skryptów wymienionych tutaj, ale żadna z pojedynczych wersji wiersza poleceń nie działała dla mnie na moim serwerze Synology NAS. renamejest niedostępna, a wiele odmian findkończy się niepowodzeniem, ponieważ wydaje się, że trzyma się starszej nazwy ścieżki, której nazwa została już zmieniona (np. jeśli znajdzie ./FOOpo niej ./FOO/BAR, zmiana nazwy ./FOOna ./foonadal będzie wyświetlana./FOO/BAR mimo że ta ścieżka nie jest już prawidłowa) . Powyższe polecenie zadziałało dla mnie bez żadnych problemów.

Poniżej znajduje się wyjaśnienie każdej części polecenia:


find . -depth -name '*[A-Z]*'

Spowoduje to znalezienie dowolnego pliku z bieżącego katalogu (przejdź .do dowolnego katalogu, który chcesz przetworzyć), używając wyszukiwania w pierwszej kolejności (np. Wyświetli listę ./foo/barwcześniej ./foo), ale tylko dla plików zawierających wielkie litery. -nameFiltr stosuje się tylko do nazwy pliku podstawa, a nie pełną ścieżkę. Więc to będzie lista, ./FOO/BARale nie ./FOO/bar. To jest w porządku, ponieważ nie chcemy zmieniać nazwy ./FOO/bar. Chcemy jednak zmienić nazwę ./FOO, ale ta jest wymieniona później (dlatego -depthjest ważna).

To polecenie samo w sobie jest szczególnie przydatne do znajdowania plików, których nazwy chcesz zmienić. Użyj tego po wykonaniu pełnego polecenia zmiany nazwy, aby wyszukać pliki, które nadal nie zostały zastąpione z powodu kolizji nazw plików lub błędów.


sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'

Ta część odczytuje pliki wyprowadzone przez findi formatuje je w mvpoleceniu przy użyciu wyrażenia regularnego. -nOpcja zatrzymuje seddrukowanie wejście, a pkomenda w poszukiwaniu i zamiany regex wyjść wymieniony tekstowych.

Samo wyrażenie regularne składa się z dwóch przechwyceń: części aż do ostatniego / (czyli katalogu pliku) i samej nazwy pliku. Katalog pozostaje nienaruszony, ale nazwa pliku jest przekształcana na małe litery. Więc jeśli findwyjścia ./FOO/BAR, to się stanie mv -n -v -T ./FOO/BAR ./FOO/bar. -nOpcja mvpilnuje istniejących plików małe nie są nadpisywane. -vOpcja sprawia, że mvwyjście każda zmiana, która czyni (albo nie robić - jeśli ./FOO/barjuż istnieje, to wysyła coś podobnego ./FOO/BAR -> ./FOO/BAR, zauważając, że żadna zmiana została dokonana). -TJest tutaj bardzo ważne - traktuje plik docelowy jako katalogu. Zapewni to, że ./FOO/BARnie zostanie on przeniesiony, ./FOO/barjeśli katalog istnieje.

Użyj tego razem z, findaby wygenerować listę poleceń, które zostaną wykonane (przydatne do sprawdzenia, co zostanie zrobione bez robienia tego)


sh

To dość oczywiste. Kieruje wszystkie wygenerowane mvpolecenia do interpretera powłoki. Możesz go zastąpić bashpowłoką lub dowolną powłoką, która Ci się podoba.

oisyn
źródło
0

Slugify Zmień nazwę (wyrażenie regularne)

Nie jest to dokładnie to, o co prosił PO, ale to, co miałem nadzieję znaleźć na tej stronie:

Wersja „slugify” służąca do zmiany nazw plików, tak aby były podobne do adresów URL (tj. Zawierają tylko znaki alfanumeryczne, kropki i myślniki):

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
cwd
źródło
2
"nie dokładnie"? to wcale nie jest to, o co prosił PO
Corey Goldberg,