Jak zmienić nazwę wielu plików, zastępując słowo w nazwie pliku?

36

Wymień ACDC na AC-DC

Na przykład mamy te pliki

ACDC - Rock N 'Roll Ain't Noise Pollution.xxx

ACDC - Rocker.xxx

ACDC - Shoot To Thrill.xxx

Chcę, aby stały się:

AC-DC - Rock N 'Roll Ain't Noise Pollution.xxx

AC-DC - Rocker.xxx

AC-DC - Shoot To Thrill.xxx

Wiem, że do tej operacji używany jest sed lub awk. Nie mogę google, więc proszę o twoją pomoc =) Czy możesz podać pełne działające polecenie powłoki dla tego zadania?

Opinia: Rozwiązanie dla użytkowników OSX

holms
źródło
1
Wydaje mi się, że jest tu większe pytanie - czy ogólnie próbujesz naprawić nazwy plików mp3? Istnieje wiele skryptów, które ludzie napisali, aby to zrobić. Myślę, że jeden, którego użyłem, został nazwany mp3fixer.
Phil Hollenback
nie, nie chodzi o mp3. Muszę tylko zarządzać dużymi plikami o podobnych nazwach i coś wszystko musi zostać wymienione lub naprawione ... powszechna sytuacja, więc potrzebuję tego sprytnego rozwiązania do zmiany nazwy wszystkich z nich
holms

Odpowiedzi:

45
rename 's/ACDC/AC-DC/' *.xxx

z man rename

DESCRIPTION
       "rename" renames the filenames supplied according to the rule specified as the 
first argument.  The perlexpr argument is a Perl expression which is expected to modify the 
$_ string in Perl for at least some of the filenames specified.  If a given filename is not 
modified by the expression, it will not be renamed.  If no filenames are given on
           the command line, filenames will be read via standard input.

Na przykład, aby zmienić nazwę wszystkich plików pasujących do „* .bak” w celu usunięcia rozszerzenia, możesz powiedzieć

rename 's/\.bak$//' *.bak

Aby przetłumaczyć wielkie litery na małe, należy użyć

rename 'y/A-Z/a-z/' *
Joel K.
źródło
5
Zauważ, że wiele maszyn linuxowych ma zmienioną nazwę z util-linux, która implementuje proste podstawianie, a nie wyrażenia regularne. Więc jeśli zmiana nazwy nie powiedzie się bezczynnie, prawdopodobnie używasz niewłaściwego rename.
Phil Hollenback
Szukałem tego od wieków! dzięki!
holms
@PhilHollenback Jak w takim razie znaleźć / zainstalować właściwy? :)
Henry
Nie działa, gdy w nazwach plików zamiast znaków spacji są podkreślenia - jak to rozwiązać?
unfa
13

Ta odpowiedź zawiera dobre części ze wszystkich innych odpowiedzi, pomijając taką herezję jak ls | while read.

Aktualny katalog:

for file in ACDC*.xxx; do
    mv "$file" "${file//ACDC/AC-DC}"
done

W tym podkatalogi:

find . -type f -name "ACDC*" -print0 | while read -r -d '' file; do
    mv "$file" "${file//ACDC/AC-DC}"
done

Znaki nowego wiersza naprawdę nie powinny znajdować się w nazwach plików, więc może to być prostsze podczas pracy z nazwami zawierającymi spacje:

find . -type f -name "ACDC*" | while read -r file; do
    mv "$file" "${file//ACDC/AC-DC}"
done
grawitacja
źródło
9

Aby użyć wersji util-linux wspomnianego renamePhila (na Ubuntu, nazywa się rename.ul):

rename ACDC AC-DC ACDC*

lub

rename.ul ACDC AC-DC ACDC*
Wstrzymano do odwołania.
źródło
1
Twój wariant jest najlepszy =) tak wiele głupich artykułów w Google o znajdowaniu, wysyłaniu i awk ... do tej prostej operacji, dla której już istnieją nazwy nazw!
Holms
4

Korzystanie z powłoki bash

find . -type f -name "ACDC*" -print0 | while read -d $'\0' f
do
   new=`echo "$f" | sed -e "s/ACDC/AC-DC/"`
   mv "$f" "$new"
done

Uwaga: użycie findspowoduje przetworzenie bieżącego katalogu i katalogów pod.

Pierścień Ø
źródło
1

Zależy od twojej powłoki. W Zsh zrobiłbym to:

for file in ACDC*.xxx; do
    mv "$file" "$(echo $file | sed -e 's/ACDC/AC-DC/')"
done

Prawdopodobnie nie najlepsze rozwiązanie, ale działa.

polemon
źródło
1

Za pomocą bash:

ls *.xxx | while read fn; do
    mv "${fn}" "${fn/ACDC/AC-DC}";
done

Jeśli masz renamezainstalowany program:

rename 's/ACDC/AC-DC/' *.xxx
ThatGraemeGuy
źródło