texto sustituir reemplazar por consola cadenas cadena archivos bash xargs

bash - sustituir - reemplazar un texto en linux



Modificar la cadena de reemplazo en xargs (8)

los archivos deben ser renombrados / movidos de <name>.txt a /foo/<name>.bar.txt

Puede usar la utilidad de rename , por ejemplo:

rename s//.txt$//.txt/.bar/g *.txt

Sugerencia: la sintaxis de sustitución es similar a sed o vim .

A continuación, mueva los archivos a un directorio de destino utilizando mv :

mkdir /some/path mv *.bar /some/path

Para renombrar archivos en subdirectorios basados ​​en alguna parte de su nombre, verifique que:

-p / --mkpath / --make-dirs Crea cualquier directorio inexistente en la ruta de destino.

Pruebas:

$ touch {1..5}.txt $ rename --dry-run "s/.txt$/.txt.bar/g" *.txt ''1.txt'' would be renamed to ''1.txt.bar'' ''2.txt'' would be renamed to ''2.txt.bar'' ''3.txt'' would be renamed to ''3.txt.bar'' ''4.txt'' would be renamed to ''4.txt.bar'' ''5.txt'' would be renamed to ''5.txt.bar''

Cuando estoy usando xargs veces no necesito usar explícitamente la cadena de reemplazo:

find . -name "*.txt" | xargs rm -rf

En otros casos, quiero especificar la cadena de reemplazo para hacer cosas como:

find . -name "*.txt" | xargs -I ''{}'' mv ''{}'' /foo/''{}''.bar

El comando anterior movería todos los archivos de texto bajo el directorio actual a /foo y agregará la bar extensión a todos los archivos.

Si en lugar de anexar algún texto a la cadena de reemplazo, quisiera modificar esa cadena de modo que pudiera insertar algún texto entre el nombre y la extensión de los archivos, ¿cómo podría hacerlo? Por ejemplo, digamos que quiero hacer lo mismo que en el ejemplo anterior, pero los archivos deben ser renombrados / movidos de <name>.txt a /foo/<name>.bar.txt (en lugar de /foo/<name>.txt.bar ).

ACTUALIZACIÓN : logro encontrar una solución:

find . -name "*.txt" | xargs -I{} / sh -c ''base=$(basename $1) ; name=${base%.*} ; ext=${base##*.} ; / mv "$1" "foo/${name}.bar.${ext}"'' -- {}

Pero me pregunto si hay una solución más corta / mejor.


Añadiendo que el artículo de la wikipedia es sorprendentemente informativo

por ejemplo:

Truco de la concha

Otra forma de lograr un efecto similar es utilizar un intérprete de comandos como el comando lanzado y tratar con la complejidad de ese shell, por ejemplo:

$ mkdir ~/backups $ find /path -type f -name ''*~'' -print0 | xargs -0 bash -c ''for filename; do cp -a "$filename" ~/backups; done'' bash


El siguiente comando construye el comando move con xargs, reemplaza la segunda aparición de ''.'' con ''.bar.'', luego ejecuta los comandos con bash, trabajando en mac OSX.

ls *.txt | xargs -I {} echo mv {} foo/{} | sed ''s//./.bar./2'' | bash


En casos como este, un ciclo while sería más legible:

find . -name "*.txt" | while IFS= read -r pathname; do base=$(basename "$pathname"); name=${base%.*}; ext=${base##*.} mv "$pathname" "foo/${name}.bar.${ext}" done

Tenga en cuenta que puede encontrar archivos con el mismo nombre en diferentes subdirectorios. ¿Estás de acuerdo con que los duplicados sean mv por mv ?


Es posible hacer esto en una sola pasada (probada en GNU) evitando el uso de asignaciones variables temporales

find . -name "*.txt" | xargs -I{} sh -c ''mv "$1" "foo/$(basename ${1%.*}).new.${1##*.}"'' -- {}


Inspirado por una respuesta de @justaname anterior, este comando que incorpora Perl one-liner lo hará:

find ./ -name /*.txt | perl -p -e ''s/^(.*//(.*)/.txt)$/mv $1 .//foo//$2.bar.txt/'' | bash


Si puedes usar algo que no sea bash / sh, Y esto es solo por un "mv" de fantasía ... puedes probar el venerable script "rename.pl". Lo uso en Linux y cygwin en Windows todo el tiempo.

http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html

rename.pl ''s/^(.*?)/.(.*)$//1-new_stuff_here./2/'' list_of_files_or_glob

También puede usar un parámetro "-p" para renombrar.pl para que le diga lo que HABRÍA HECHO, sin hacerlo realmente.

Acabo de probar lo siguiente en mi c: / bin (entorno cygwin / windows). Usé el "-p" para escupir lo que habría hecho. Este ejemplo solo divide la base y la extensión, y agrega una cadena entre ellos.

perl c:/bin/rename.pl -p ''s/^(.*?)/.(.*)$//1-new_stuff_here./2/'' *.bat rename "here.bat" => "here-new_stuff_here.bat" rename "htmldecode.bat" => "htmldecode-new_stuff_here.bat" rename "htmlencode.bat" => "htmlencode-new_stuff_here.bat" rename "sdiff.bat" => "sdiff-new_stuff_here.bat" rename "widvars.bat" => "widvars-new_stuff_here.bat"