/ / Rinomina più file modificando l'estensione e parte della stringa: bash, shell, xargs

Rinominare più file cambiando l'estensione e parte della stringa - bash, shell, xargs

Ho una lista di *.new file in una directory. Questo file contiene D1 nei loro nomi che devono essere sostituiti D2 e anche rimuovere l'estensione da .new a nothing

hello_world_D1_122.txt.new -------> hello_world_D2_122.txt

Quello che ho provato è

ls -slt | grep -iE "*.new$" | awk -F " " "{print $10}" | xargs -I {} mv {} "echo {} | sed -e "s/.D1./.D2./g ; s/.new//g""

Questo comando non produce l'output richiesto. L'output del comando precedente è

mv: rename hello_world_D1_122.txt.new to echo hello_world_D1_122.txt.new | sed -e "s/D1/D2/g ; s/.new//g": No such file or directory

risposte:

1 per risposta № 1

Il tuo tentativo attuale contiene un gran numero di problemi oltre all'ovvio errore di sintassi.

L'argomento "echo {} | sed "..."" è una stringa letterale; non c'è alcun modo xargs potrebbe interpretarlo come un comando (anche se ovviamente lo sostituirà {} con il nome del file all'interno di questa stringa).

Inoltre, non usare ls negli script e se proprio devi, usando ls -l e poi buttare via il formato lungo è ... solo sciocco, oltre che inefficiente e soggetto a errori (vedi il link per i dettagli).

Il modo ovvio e superiore per risolvere questo è senza xargs:

for f in ./*.new; do
[ -f "$f" ] || continue   # in case the glob matches no files
d=${f%.new}               # trim off extension
mv "$f" "${d/.D1./.D2.}"  # replace .D1. with .D2.
done

(Immagino che tu voglia sostituire i punti letterali, anche se la tua regex corrisponderebbe a qualsiasi personaggio tranne la nuova riga seguita da D1 seguito da qualsiasi carattere tranne newline.)

Se insisti su un xargs soluzione, puoi avvolgere lo script sopra bash -c "..." e passa a quello xargs:

printf "%s" ./*.new | xargs -r0 bash -c "for f; do d=${f%.new}; mv "$f" "${d/.D1./.D2.}"; done" _

4 per risposta № 2

Perché tutto sommato sui modi usando un sacco di strumenti shell, puoi usare bash strumento incorporato per questo, usando la sintassi di espansione dei parametri per la manipolazione delle stringhe

for file in *.new; do
[ -f "$file" ] || continue
temp="${file%*.new}"
mv -- "${file}" "${temp/D1/D2}"
done

La parte "${file%*.new}" strisce dell'estensione .new dal nome del file e "${temp/D1/D2}" sostituisce D1 con D2

"Non ho idea del perché la persistenza nell'uso di GNU xargs, ma puoi usare questo modo non leggibile per farlo. utilizzando printf per elencare i file con delimit null e usare xargs -0 leggere con null come carattere delimitatore,

printf "%s" *.new | xargs -0 -r -I {} sh -c "temp="${0%*.new}"; mv -- "${0}" "${temp/D1/D2}"" {}

1 per risposta № 3

Usando GNU Paralllel è simile al seguente:

parallel mv {} "{=s/D1/D2/;s/.new//=}" ::: *.new

Se hai nomi di file pazzi:

touch "$(printf "Shell  Specialnn"*$!_D1_txt.new")"
parallel -0 mv {} "{=s/D1/D2/;s/.new//=}" ::: *.new