jak zmienić nazwę wielu plików, zastępując ciąg w nazwie pliku? ten ciąg zawiera „#”

42

https://serverfault.com/questions/70939/how-to-replace-a-text-string-in-multiple-files-in-linux

https://serverfault.com/questions/228733/how-to-rename-multiple-files-by-replacing-word-in-file-name

https://serverfault.com/questions/212153/replace-string-in-files-with-certain-file-extension

https://serverfault.com/questions/33158/searching-a-number-of-files-for-a-string-in-linux

Wszystkie wymienione artykuły odpowiedziały na moje pytanie. Jednak żaden z nich nie działa dla mnie. Podejrzewam, że dzieje się tak, ponieważ ciąg, który próbuję zastąpić, zawiera #. Czy istnieje specjalny sposób rozwiązania tego problemu?

Mam plik obrazu, który został zastąpiony przez é # U00a9 podczas migracji witryny. Wyglądają tak:

Lucky-#U00a9NBC-80x60.jpg
Lucky-#U00a9NBC-125x125.jpg
Lucky-#U00a9NBC-150x150.jpg
Lucky-#U00a9NBC-250x250.jpg
Lucky-#U00a9NBC-282x232.jpg
Lucky-#U00a9NBC-300x150.jpg
Lucky-#U00a9NBC-300x200.jpg
Lucky-#U00a9NBC-300x250.jpg
Lucky-#U00a9NBC-360x240.jpg
Lucky-#U00a9NBC-400x250.jpg
Lucky-#U00a9NBC-430x270.jpg
Lucky-#U00a9NBC-480x240.jpg
Lucky-#U00a9NBC-600x240.jpg
Lucky-#U00a9NBC-600x250.jpg
Lucky-#U00a9NBC.jpg

i chcę to zmienić na coś takiego:

Lucky-safeNBC-80x60.jpg
Lucky-safeNBC-125x125.jpg
Lucky-safeNBC-150x150.jpg
Lucky-safeNBC-250x250.jpg
Lucky-safeNBC-282x232.jpg
Lucky-safeNBC-300x150.jpg
Lucky-safeNBC-300x200.jpg
Lucky-safeNBC-300x250.jpg
Lucky-safeNBC-360x240.jpg
Lucky-safeNBC-400x250.jpg
Lucky-safeNBC-430x270.jpg
Lucky-safeNBC-480x240.jpg
Lucky-safeNBC-600x240.jpg
Lucky-safeNBC-600x250.jpg
Lucky-safeNBC.jpg

AKTUALIZACJA:

Wszystkie te przykłady zaczynają się od „LU00a9ucky, ale tutaj jest wiele obrazów o różnych nazwach. Po prostu celuję w część„ # U00a9 ”ciągu znaków, aby zastąpić ją„ bezpieczną ”.

Społeczność
źródło
3
Więc czego tak naprawdę próbowałeś? Widzę, że połączyłeś się z kilkoma pytaniami i powiedziałeś, że się nie udało, ale jak się nie udało? IMO najlepszy przykład używa renamepolecenia. Podejrzewam, że twoja zmiana nazwy byłaby tak prosta jak rename -n 's/#/safeNBC/' *.jpg.
Zoredache,
Próbowałem rename -n 's/#U00a9/safe/' *.jpgi polecenie zostało zaakceptowane, ale nie nastąpiły żadne zmiany.
Oczywiście, jak można zauważyć w dokumentacji, którą z pewnością sprawdziłeś, -njest to no actopcja. Co pozwala zobaczyć, czy to działa, zanim faktycznie go użyjesz. Czy dane wyjściowe na ekranie poprawnie wyświetlały potencjalne nowe nazwy?
Zoredache,
Przepraszam, że skopiowałem i wkleiłem twój przykład, nie zwracając pełnej uwagi, wykonałem polecenie zmiany nazwy bez -n. Uważam, że @DTK rozwiązuje problem, nie uciekałem #.
Zastępowanie ciągów w nazwach plików w systemie MacOS: superuser.com/questions/152627/…
Anton Tarasenko

Odpowiedzi:

64

Aby zastąpić #przez somethingelsenazw plików w bieżącym katalogu (nie rekurencyjnego) można użyć GNU zmiany nazwy narzędzia:

rename  's/#/somethingelse/' *

Znaki takie -muszą być poprzedzone znakiem ucieczki \.

W twoim przypadku chciałbyś użyć

rename 's/#U00a9/safe/g' *

Zauważ, że jeśli chcesz operować tylko na pewnym zaznaczeniu plików, np. Tylko *.jpg, dostosuj końcowe dane wejściowe, aby pasowały do ​​tego wyboru:

rename 's/#U00a9/safe/g' *.jpg

Aby wykonać test przed faktyczną zmianą nazw plików, użyj -nflagi:

demo/> ls                               
Lucky-#U00a9NBC-125x125.jpg  
Lucky-#U00a9NBC-150x150.jpg 

demo/> rename -n 's/#U00a9/safe/g' *.jpg
rename(Lucky-#U00a9NBC-125x125.jpg, Lucky-safeNBC-125x125.jpg)
rename(Lucky-#U00a9NBC-150x150.jpg, Lucky-safeNBC-150x150.jpg)

Dla OS X, GNU zmiany nazwy można zainstalować przy użyciu homebrew : brew install rename.

KrisWebDev
źródło
To nie działało na moim komputerze (Arch Linux), ale odpowiedź mika zadziałała.
marcvangend
@marcvangend Której wersji renameużywasz? # sudo pacman -S perl-renamezainstaluje wersję Perla, która jest potężniejsza i może wystarczyć, aby ta odpowiedź działała dla Ciebie.
John Gowers,
@JohnGowers Thanks! Nie wiedziałem, że są dwie wersje. W moim systemie rename --versionzwraca, rename from util-linux 2.29.2więc to naprawdę nie jest wersja perla.
marcvangend
5
Istnieją dwa popularne renamenarzędzia, ale żadne z nich nie jest rozwijane przez GNU: dystrybucje oparte na Debianie zawierają renamenarzędzie wraz z pakietem Perla, podczas gdy dystrybucje oparte na Red Hat korzystają z renamenarzędzia z util-linuxLinux Kernel Organization. Twój link prowadzi do funkcjirename C ze standardowej biblioteki GNU.
Anthony G - sprawiedliwość dla Moniki
2
W tej odpowiedzi, dlaczego mamy pisać /gwrename 's/#U00a9/safe/g' *
Nikhil
21

znajdź listę plików, a następnie zastąp słowo kluczowe. poniżej jest przykład

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;
Sujit Dhamale
źródło
1
Potrzebne są podwójne cudzysłowy wokół mvargumentów, na wypadek, gdyby w nazwie były spacje
Stop Harming Monica
Musiałem zamienić wszystkie pliki * _spec.rb na * _controller_spec.rb, a twoje rozwiązanie działało dla mnie. Dzięki
jedi
18

Nie jest to trudne, po prostu pamiętaj, aby uciec przed nazwą oktotorpe (#), przygotowując odwrotny ukośnik (\).

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 
Społeczność
źródło
Twoje wyjaśnienie ma sens, unikając #dźwięków, których potrzebuję. Nie widzę odwrotnego ukośnika w twoim przykładzie. Czy powinno to wyglądać tak: s/\#U00a9/safe/
@LeonFrancisShelhamer good catch. Połknął ukośnik. Zmodyfikuję.
17

Aby uciec #z powłoki, użyj pojedynczych cudzysłowów ( '#'), podwójnych cudzysłowów ( "#") lub odwrotnego ukośnika ( \#).

Najprostszym w twoim przypadku byłoby użycie renamepolecenia (jeśli jest dostępne):

rename '#U00a9' safe *.jpg
mik
źródło
2
Dzięki. Chociaż najwyżej głosowana odpowiedź ( rename 's/#/somethingelse/' *) nie działała na moim komputerze (Arch Linux), ta właśnie działała.
marcvangend 21.04.17
1
Działa to przy użyciu polecenia rename z programu ut-linux.
imclean
10

nie wiem jak to zrobić, ale możesz spróbować tego w powłoce bash:

for f in Lucky-#U00a9NBC-*.jpg; do mv -v "$f" "${f/#U00a9/safe}"; done;

wyjaśnienie:

  1. zapętla wszystkie nazwy plików pasujące do glob (Lucky- # U00a9NBC - *. jpg)
  2. zmienia nazwę pliku za pomocą polecenia move (mv)
  3. używa natywnego podstawienia parametru bash $ {var / Pattern / Replacement} do stworzenia nowej nazwy („$ {f / # U00a9 / safe}”)

Więcej informacji na temat zastępowania parametrów (co jest wysoce niewykorzystanym IMO): http://www.tldp.org/LDP/abs/html/parameter-substitution.html

Gregory Patmore
źródło
Chociaż ten kod może odpowiedzieć na pytanie, sam w sobie nie jest zbyt użyteczny. Wyjaśnienie, w jaki sposób rozwiązuje problem, poprawiłoby użyteczność i długoterminową wartość odpowiedzi.
Anthony G - sprawiedliwość dla Moniki
dodano objaśnienie instrukcji i dalsze czytanie zgodnie z komentarzem Anthony'ego.
Gregory Patmore,
1

Powyższe przykłady nie działały w moim systemie (CentOS 5.6), więc znalazłem (prawdopodobnie bardziej specyficzne dla systemu) polecenie, które działa (uwaga: trzeba uciec z '#' z \linii poleceń):

rename \#U00a9 safe *.jpg

[Również: Nie mam jeszcze wystarczającej reputacji, aby móc komentować, więc w odpowiedzi na pytanie Nikhila dotyczące użycia /gin rename 's/old_string/new_string/g'(zamieszczone w komentarzach do innej odpowiedzi powyżej):

Użyj gmodyfikatora, aby wykonać podstawienie „globalne” (to znaczy zastąpić new_string old_string tyle razy, ile wystąpi old_string). Nie powinno to być konieczne w mojej odpowiedzi, ponieważ renamezostanie zastosowane do wszystkich plików określonych za pomocą *. Zobacz https://www.computerhope.com/unix/rename.htm, aby uzyskać zwięzłe wyjaśnienie tego i innych modyfikatorów.]

Ezra Citron
źródło
Poprawny; Systemy operacyjne pochodzące z Fedory, takie jak CentOS, mają inną wersję renameniż systemy operacyjne oparte na Debianie. Zobacz unix.stackexchange.com/a/238862/135943 . Nawiasem mówiąc, CentOS 5.6 jest dość stary i polecam aktualizację.
Wildcard,
Ach, dziękuję za wyjaśnienie + link. Przestarzały system operacyjny działa, więc nie do mnie należy uaktualnienie :), ale budowany jest nowy klaster i prawdopodobnie uaktualnimy się, gdy przejdziemy ...
Ezra Citron
0

Oto rozwiązanie DTK opakowane w funkcję bash wielokrotnego użytku:

function renameFilesRecursively () {

  SEARCH_PATH="$1"
  SEARCH="$2"
  REPLACE="$3"

  find ${SEARCH_PATH} -type f -name "*${SEARCH}*" | while read FILENAME ; do
      NEW_FILENAME="$(echo ${FILENAME} | sed -e "s/${SEARCH}/${REPLACE}/g")";
      mv "${FILENAME}" "${NEW_FILENAME}";
  done

}

Oto jak możesz go użyć:

renameFilesRecursively /home/user/my-files apple orange
Slava Fomin II
źródło
0

W rzeczywistości renamema opcję dokładnie dla tego zwanego --substlub -sw skrócie. Nie trzeba używać składni wyrażenia regularnego.

rename -s '#U00a9' 'safe' *

Jeśli chcesz zastąpić / zastąpić wiele wystąpień, użyj --subst-alllub -S.

BTW, chciałem tylko zamienić ciąg znaków na nic (usunąć go z nazwy pliku) ... cóż, mamy również opcję -d/--deletei -D/--delete-all:

rename -d '#U00a9' *
Lapin
źródło
-1

Inną opcją jest użycie pyRenameraplikacji stworzonej specjalnie do zmiany nazwy partii.

Można go zainstalować za pomocą sudo apt-get install pyrenamer

Szczegółowe informacje na temat użytkowania znajdują się w pliku README w serwisie GitHub .

Sajna T.
źródło
1
Jeśli naprawdę uważasz, że to może odpowiedzieć na pytanie, dodaj wyjaśnienie do swojej odpowiedzi. Sam w sobie instaluje tylko pakiet. Powinieneś wyjaśnić, co robi polecenie i podać przykład, który obsługuje konkretne wymaganie PO.
roaima