Masowa zmiana nazwy, wersja * nix

11

Szukałem sposobu na zmianę nazwy ogromnej liczby plików o podobnych nazwach, bardzo podobnych do tego (pytanie związane z systemem Windows), z wyjątkiem tego, że używam * nix (osobno dla Ubuntu i FreeBSD). Podsumowując, używając powłoki (Bash, CSH itp.) Jak masowo zmienić nazwy wielu plików, na przykład następujące pliki:

Beethoven - Fur Elise.mp3
Beethoven - Moonlight Sonata.mp3
Beethoven - Oda do radości.mp3
Beethoven - Rage Over the Lost Penny.mp3

zostanie przemianowany w ten sposób?

Fur Elise.mp3
Moonlight Sonata.mp3
Oda do radości.mp3
Rage Over the Lost Penny.mp3

Powodem, dla którego chcę to zrobić, jest to, że zbiór plików przejdzie do katalogu o nazwie „Beethoven” (tj. Przedrostek nazw plików), a posiadanie tych informacji w samej nazwie pliku będzie zbędne.

Paolo B.
źródło

Odpowiedzi:

12

Narzędzie zmiany nazwy zrobi to, co chcesz.

Po prostu użyj rename 's/Beethoven\ -\ //g' *.mp3


źródło
Czy możesz edytować, aby podać link do narzędzia, czy jest to standard w obu wymienionych dystrybucjach (Ubuntu i FreeBSD)?
Chris W. Rea,
1
Pochodzi z Perlem. Debian używa go jako polecenia zmiany nazwy, więc podejrzewam, że także Ubuntu. Jest jeszcze jedno polecenie zmiany nazwy, które jest bezwartościowe, więc sprawdź stronę podręcznika.
derobert
wow, składnia zmiany nazwy wygląda bardzo podobnie do vim replace: D
Dzung Nguyen
port w / usr / ports / sysutils / rename działał doskonale w FreeBSD
Josh W.
10

Podobnie jak wiele innych rzeczy w Linuksie / Uniksie, jest na to więcej niż jeden sposób!

Niektórzy mogą użyć mmv (masa mv).

Polecenie rename lub prename, które jest dostarczane z niektórymi pakietami Perla (nowsze wersje Ubuntu i Debian), może to zrobić.

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

Zauważ, że narzędzie zmiany nazwy w Fedorze 10 nie jest tym samym programem i działa inaczej. Jest częścią innego pakietu, util-linux-ng i można go znaleźć tutaj .

Często po prostu chodzę do powłoki, by zrezygnować z przyzwyczajenia (w końcu takie narzędzia nie zawsze istniały).

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

Spowoduje to utworzenie katalogu Beethoven, a następnie przeniesienie pliku do tego katalogu / nazwa pliku, gdzie nazwa pliku ma „Beethoven -” zastąpiony niczym.

W ramach testu przed:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

Po:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3
jtimberman
źródło
4

Wypróbuj to rozwiązanie, zaimplementowane przy użyciu kombinacji grep i zmiany nazwy. Zakłada się, że masz całą masę katalogów, których nazwę musisz zmienić. Jeśli jest ich tylko kilka, wybrałbym podejście ręczne, ze schematem „Artist -” na stałe dla każdego.

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

Objaśnienie find :
Polecenie find wyszukuje wszystkie pliki z rozszerzeniem .mp3 w bieżącej hierarchii plików i wywołuje argument przekazywany do -exec dla każdego. Należy zauważyć, że w ciągu -exec , {} odnosi się do argumentu przekazanego przez znaleziska (plik ścieżka + nazwa). W \;gwarantuje ;zostanie przekazany do zmiany nazwy i zamiast wskazujący koniec find polecenia.

Powyższe polecenie ma przełącznik -n (brak akcji); dlatego powie ci tylko, co by się stało, gdybyś go uruchomił. Polecam uruchomienie tego polecenia bez przełącznika -n tylko po uruchomieniu go raz i jesteś zadowolony z proponowanych wyników.

Teraz regexp.

  • ^ dopasowuje początek łańcucha.
  • $ dopasowuje koniec łańcucha.
  • . pasuje do dowolnej postaci.
  • *oznacza zero lub więcej poprzedniej konstrukcji. np. .*oznacza zero lub więcej znaków.
  • \s oznacza dowolny znak spacji.
  • \S oznacza dowolny znak spacji.
  • Wszystko wewnątrz ()zostaje schwytane i jest odzwierciedlane jako $1, $2w zależności od jego pozycji.

Wyrażenie regularne:

  • Na początku szuka opcjonalnej struktury katalogów, przechwytuje to w 1 USD: (.*/)
  • Pomija wszystko do „ -”:.*-
  • Przechwytuje resztę ciągu, z wyjątkiem spacji wiodących i końcowych, w 2 USD: (.*)
  • Przepisuje plik na 1 $ 2 $, który powinien brzmieć „/path/to/file/""filename.mp3”

Oto mój testowy przebieg:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

Regexp to trudna sprawa i napisałem wiele błędów, więc chętnie przyjmę wszelkie uwagi na temat braku zalet tego. Wiem, że znalazłem sporo testujących to.


źródło
1

Przygotowałem program Java wiersza polecenia, który sprawia, że ​​zmiana nazw plików (i katalogów) jest dziecinnie prosta, szczególnie w przypadku skryptów. Jest darmowy i open source, więc możesz go zmodyfikować do treści twojego serca:

RenameWand
http://renamewand.sourceforge.net/

Kilka odpowiednich przykładów użycia:

Przenieś pliki formularza "<a> - <b>"do odpowiedniego katalogu "<a>":

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

Sortuj pliki według czasu ostatniej modyfikacji i zmieniaj ich nazwy za pomocą 3-cyfrowej liczby:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

Zmień kolejność części nazwy pliku i zmień wielkość liter:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"
Zach Scrivena
źródło
1

zmv Narzędzie zmiany nazwy zsh jest bardzo dobre.

# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase

Więcej notatek tutaj ...

ocodo
źródło
0

W przypadku głów Penguin można to łatwo zrobić za pomocą skryptu powłoki lub skryptu AWK. Dla nas, zwykłych śmiertelników, możesz spróbować Midnight Commander. Występuje w większości dystrybucji Linuksa, począwszy od znaku zachęty powłoki mc -a. Możesz zmieniać nazwy plików za pomocą wyrażeń regularnych. Użyłem tego artykułu z GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/, aby mi pomóc.

TechScott
źródło
0

Oto prosty przykład wiersza polecenia. Miałem słowo „biały” pośrodku nazw plików png. Chciałem go wyjąć i zostawić tylko jeden znak podkreślenia. To załatwiło sprawę:

for i in *.png; do mv "$i" "${i/white/}"; done
William Jockusch
źródło
0

Użyj vidir, a następnie użyj funkcji edytora, aby zastosować wzorzec zmiany nazwy.

IMIĘ

vidir - edycja katalogu

STRESZCZENIE

vidir [--verbose] [katalog | plik | -] ...

OPIS

vidir pozwala na edycję zawartości katalogu w edytorze tekstu. Jeśli nie określono katalogu, bieżący katalog jest edytowany.

Podczas edycji katalogu każdy element w katalogu pojawi się w osobnym, ponumerowanym wierszu. Te liczby to sposób, w jaki vidir śledzi zmiany przedmiotów. Usuń wiersze, aby usunąć pliki z katalogu, lub edytuj nazwy plików, aby zmienić nazwy plików. Możesz także zamieniać pary liczb w celu zamiany nazw plików.

Zauważ, że jeśli jako katalog do edycji podano „-”, to odczytuje listę nazw plików ze standardowego wejścia i wyświetla te do edycji. Alternatywnie listę plików można podać w wierszu poleceń.

PRZYKŁADY

vidir vidir * .jpeg Typowe zastosowania.

znajdź | vidir - edytuj także zawartość podkatalogu. Aby usunąć podkatalogi, usuń całą ich zawartość i sam podkatalog w edytorze.

znajdź -type f | vidir - Edytuj wszystkie pliki w bieżącym katalogu i podkatalogach.

AUTOR

Joey Hess 2006-2010

Modyfikacje autorstwa Magnusa Woldricha 2011

PRAWO AUTORSKIE

Copyright 2006-2011 vidir „AUTOR” wymienione powyżej.

Licencjonowany na licencji GNU GPL.

Peter Eisentraut
źródło
0

Na * nix bez perla renamedostępne

W niektórych * nix zmiana nazwy nie jest dostępna, więc należy zmienić nazwę za pomocą innej metody. Kilka lat temu zasugerowałem zmvtutaj, która, choć świetna, niekoniecznie jest dostępna.

Używając wbudowanych i sed, możemy szybko zrobić skrypt powłoki, aby to zrobić, co daje nam bardzo podobną składnię do skryptu zmiany nazwy perla, a mimo braku pewności obsługi błędów, wykonuje zadanie.

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Stosowanie

sedrename 's/Beethoven\ -\ //g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Powiedzmy, że chcieliśmy również utworzyć foldery docelowe ...

Ponieważ mvnie tworzy folderów, których nie możemy używać sedrenametak, jak tutaj, ale jest to dość niewielka zmiana, więc myślę, że fajnie byłoby też to uwzględnić.

Potrzebujemy funkcji narzędzia abspath(lub ścieżki bezwzględnej), abyśmy mogli wygenerować folder docelowy dla wzorca sed / rename, który zawiera nową strukturę folderów.

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

Zapewni to, że znamy nazwy naszych folderów docelowych. Kiedy zmieniamy nazwę, będziemy musieli użyć jej w nazwie pliku docelowego.

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

Oto skrypt obsługujący pełny folder ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Oczywiście nadal działa, gdy nie mamy również określonych folderów docelowych.

Jeśli chcielibyśmy umieścić wszystkie utwory w folderze, ./Beethoven/możemy to zrobić:

Stosowanie

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

Runda bonusowa ...

Za pomocą tego skryptu przenieś pliki z folderów do jednego folderu:

Zakładając, że chcemy zebrać wszystkie dopasowane pliki i umieścić je w bieżącym folderze, możemy to zrobić:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Uwaga na wzorce wyrażeń regularnych sed

W tym skrypcie obowiązują reguły regularnych wzorców sed, wzorce te nie są PCRE (wyrażenia regularne zgodne z Perl). Możesz mieć rozszerzoną składnię wyrażeń regularnych, używając jednej sed -rlub w sed -E zależności od platformy.

Zobacz zgodny z POSIX man re_formatpełny opis podstawowych i rozszerzonych wzorców wyrażeń regularnych sed.

ocodo
źródło