come rinominare più file sostituendo la stringa nel nome del file? questa stringa contiene un "#"


43

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

Tutti questi articoli citati hanno risposto alla mia domanda. Tuttavia nessuno di loro lavora per me. Sospetto che sia perché la stringa che sto cercando di sostituire contiene un #. C'è un modo speciale per affrontare questo?

Ho un file immagine che è stato sostituito da un # U00a9 durante una migrazione del sito. Questi assomigliano a questo:

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

e voglio cambiarlo in qualcosa del genere:

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

AGGIORNARE:

Tutti questi esempi iniziano con "LU00a9ucky ma qui ci sono molte immagini con nomi diversi. Sto semplicemente prendendo di mira la parte" # U00a9 "della stringa da sostituire con" safe ".


3
Quindi cosa hai effettivamente provato? Vedo che ti sei collegato ad alcune domande e dici che hanno fallito, ma come hanno fallito? IMO il miglior esempio usa il renamecomando. Sospetto che la tua ridenominazione sarebbe semplice come rename -n 's/#/safeNBC/' *.jpg.
Zoredache,

Ho provato rename -n 's/#U00a9/safe/' *.jpge il comando è stato accettato ma non si sono verificati cambiamenti.

Certo, come avresti visto dalla documentazione che hai sicuramente rivisto, questa -nè l' no actopzione. Ciò ti consente di vedere se funziona prima di utilizzarlo effettivamente. L'output sullo schermo ha mostrato correttamente i potenziali nuovi nomi?
Zoredache,

Mi scuso per aver copiato e incollato il tuo esempio senza prestare piena attenzione, ho eseguito il comando rename senza il -n. Credo che @DTK risolva il problema, non stavo sfuggendo al #.

Sostituzione delle stringhe nei nomi dei file su MacOS: superuser.com/questions/152627/…
Anton Tarasenko,

Risposte:


65

Per sostituire #con somethingelseper i nomi di file nella directory corrente (non ricorsiva) è possibile utilizzare l' utilità di rinomina GNU :

rename  's/#/somethingelse/' *

I personaggi come -devono essere sfuggiti a \.

Per il tuo caso, ti consigliamo di utilizzare

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

Si noti che se si desidera operare solo su una determinata selezione di file, ad esempio solo *.jpg, regolare l'input finale in modo che corrisponda a tale selezione:

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

Per eseguire un test prima di modificare effettivamente i nomi dei file, utilizzare il -nflag:

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)

Per OS X, GNU rinomina può essere installato utilizzando homebrew : brew install rename.


Questo non ha funzionato sulla mia macchina (Arch Linux), ma la risposta di Mik ha fatto.
marcvangend,

@marcvangend Quale versione di renamestai usando? # sudo pacman -S perl-renameinstallerà la versione perl, che è più potente e potrebbe essere sufficiente per far funzionare questa risposta per te.
John Gowers,

@JohnGowers Grazie! Non mi rendevo conto che ci sono due versioni. Sul mio sistema, rename --versionritorna in rename from util-linux 2.29.2modo che non sia davvero la versione perl.
marcvangend,

5
Esistono due renameutility comuni, ma nessuna di esse è sviluppata da GNU: le distribuzioni basate su Debian includono renameun'utilità con il loro pacchetto Perl mentre le distribuzioni basate su Red Hat usano l' renameutilità dalla util-linuxLinux Kernel Organization. Il tuo collegamento è alla funzionerename C dalla libreria standard GNU.
Anthony G - giustizia per Monica il

2
In questa risposta, perché dobbiamo scrivere /ginrename 's/#U00a9/safe/g' *
Nikhil

24

trova l'elenco dei file e quindi sostituisci la parola chiave. sotto è un esempio

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;

1
Hai bisogno di alcune virgolette attorno ai tuoi mvargomenti, nel caso in cui ci siano spazi nel nome
Stop Harming Monica

Ho dovuto sostituire tutti i file da * _spec.rb a * _controller_spec.rb e la tua soluzione ha funzionato per me. Grazie.
jedi

Grazie. Questo risolve il mio problema
Fabio Souza il

19

Questo non è difficile, assicurati semplicemente di sfuggire all'ottotorpe (#) nel nome anteponendo una barra inversa (\).

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 

La tua spiegazione ha senso, sfuggendo ai #suoni come quello di cui ho bisogno. Non vedo una barra rovesciata nel tuo esempio. Dovrebbe apparire così: s/\#U00a9/safe/

@LeonFrancisShelhamer buona cattura. Ha ingoiato la barra rovesciata. Lo modificherò.

17

Per uscire #dalla shell, usa solo virgolette singole ( '#'), virgolette doppie ( "#") o barra rovesciata ( \#).

Il più semplice nel tuo caso sarebbe usare il renamecomando (se è disponibile):

rename '#U00a9' safe *.jpg

2
Grazie. Mentre la risposta più votata ( rename 's/#/somethingelse/' *) non ha funzionato sulla mia macchina (Arch Linux), questa ha funzionato.
marcvangend,

1
Funziona usando il comando rename di util-linux.
imclean

10

non sono sicuro di come sed, ma puoi provarlo in una shell bash:

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

spiegazione:

  1. scorre tutti i nomi di file corrispondenti al glob (Lucky- # U00a9NBC - *. jpg)
  2. rinomina il file usando il comando move (mv)
  3. usa la sostituzione nativa dei parametri bash $ {var / Pattern / Replacement} per creare il nuovo nome ("$ {f / # U00a9 / safe}")

Maggiori informazioni sulla sostituzione dei parametri (che è altamente sottoutilizzata IMO): http://www.tldp.org/LDP/abs/html/parameter-substitution.html


Sebbene questo codice possa rispondere alla domanda, non è molto utile da solo. Spiegare come risolve il problema migliorerebbe l'utilità e il valore a lungo termine della risposta.
Anthony G - giustizia per Monica,

aggiunta spiegazione dettagliata e ulteriore lettura secondo il commento di Anthony.
Gregory Patmore,

1

Gli esempi sopra non funzionavano sul mio sistema (CentOS 5.6) quindi ho trovato un comando (forse più specifico del sistema) che funziona (nota: è necessario uscire da '#' con \dalla riga di comando):

rename \#U00a9 safe *.jpg

[Inoltre: non ho ancora abbastanza reputazione per commentare, quindi in risposta alla domanda di Nikhil sull'uso di /gin rename 's/old_string/new_string/g'(posta nei commenti per un'altra risposta sopra):

Utilizzare il gmodificatore per eseguire una sostituzione "globale" (ovvero sostituire new_string con old_string tutte le volte che si verifica old_string). Questo non dovrebbe essere necessario nella mia risposta perché renameverrà applicato a tutti i file specificati con *. Vedi https://www.computerhope.com/unix/rename.htm per una spiegazione concisa di questo e altri modificatori.]


Corretta; I sistemi operativi derivati ​​da Fedora come CentOS hanno una versione diversa renamerispetto ai sistemi operativi derivati ​​da Debian. Vedi unix.stackexchange.com/a/238862/135943 . E a proposito, CentOS 5.6 è piuttosto vecchio e ti consiglio di aggiornare.
Wildcard il

Ah, grazie per la spiegazione + link. Il sistema operativo obsoleto è al lavoro e quindi non spetta a me aggiornarlo :) ma è in fase di creazione un nuovo cluster e presumibilmente aggiorneremo quando passeremo oltre ...
Ezra Citron

0

Ecco la soluzione di DTK racchiusa in una funzione bash riutilizzabile:

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

}

Ecco come puoi usarlo:

renameFilesRecursively /home/user/my-files apple orange

0

In realtà renameha un'opzione esattamente per quella chiamata --substo -sin breve. Non è necessario utilizzare la sintassi regex.

rename -s '#U00a9' 'safe' *

Se si desidera sostituire / sostituire più occorrenze, utilizzare --subst-allo -S.

A proposito, volevo solo sostituire una stringa con niente (rimuoverla dal nome del file) ... beh, abbiamo anche un'opzione per essa -d/--deletee -D/--delete-all:

rename -d '#U00a9' *

-1

Un'altra opzione è utilizzare pyRenamer, un'applicazione creata appositamente per la ridenominazione batch.

Può essere installato con sudo apt-get install pyrenamer

Per i dettagli sull'uso, consultare il file README su GitHub .


1
Se pensi davvero che questo possa rispondere alla domanda, aggiungi qualche spiegazione alla tua risposta. Di per sé, installa solo un pacchetto. Dovresti spiegare cosa fa il comando e fornire un esempio che gestisca i requisiti specifici del PO.
roaima,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.