Sobrescribir files encontrados por find?

Tengo una list de files

-rw-rw-r-- 1 tt 24813 Oct 23 2002 fig8_21.gif -rw-rw-r-- 1 tt 2259 Oct 23 2002 fig8_21t.gif -rw-rw-r-- 1 tt 35331 Oct 23 2002 fig8_23.gif -rw-rw-r-- 1 tt 2610 Oct 23 2002 fig8_23t.gif -rw-rw-r-- 1 tt 19970 Oct 23 2002 fig8_24.gif -rw-rw-r-- 1 tt 2019 Oct 23 2002 fig8_24t.gif -rw-rw-r-- 1 tt 54623 Oct 23 2002 fig8_3.gif -rw-rw-r-- 1 tt 3657 Oct 23 2002 fig8_3t.gif -rw-rw-r-- 1 tt 35861 Oct 23 2002 fig8_4.gif -rw-rw-r-- 1 tt 2344 Oct 23 2002 fig8_4t.gif 

Quiero sobrescribir <...>t.gif con <...>.gif fig8_4.gif por ejemplo, copyr fig8_4.gif para sobrescribir fig8_4t.gif .

Primero encuentro esos <...>t.gif files <...>t.gif por find . -regex ".*t\.gif" find . -regex ".*t\.gif" . Entonces quiero usar el basename para quitar los nombres de los files, pero ¿por qué tengo las siguientes advertencias?

 $ find . -regex ".*t\.gif" -execdir basename {} \; find: The relative path `~/program_files/internet/SSH_tunneling/' is included in the PATH environment variable, which is insecure in combination with the -execdir action of find. Please remove that entry from $PATH $ find . -regex ".*t\.gif" | xargs basename basename: extra operand './f10_1t.gif' 

¿Cómo voy a continuar para terminar mi tarea?

¿Es posible no usar find ?

Si es posible. Una forma de hacerlo podría ser así:

 cd /den/of/gifs && \ for f in ./*t.gif; do mv -- "${f%%t.gif}.gif" "$f" done 

La cosa ${var%%pattern} es la syntax estándar / POSIX sh para eliminar la cadena más larga que coincide con el patrón desde el final de $var .

Para que sea aún más compacto y rápido, puedes usar parallel :

 parallel mv {} {.}t.gif :::: <(find . -regex '.+[0-9].gif') 

La expresión después de :::: proporciona arguments para parallel . Estos arguments se usan luego usando {} . {.} Representa el argumento sin la extensión de file. Entonces, en nuestro caso {} serán los nombres de file de files sin la t en ellos, por ejemplo fig8_4.gif . {.} sería entonces fig8_4 .

Si quieres quedarte con find y basename , esto debería funcionar:

 find . -name "*.gif" ! -name "*t.gif" -execdir sh -c ' cp -- "$0" "$(basename "$0" .gif)t.gif"' {} \; 

Esto no es la mejor opción en términos de performance y resources.

Sobre tus errores:

find: la ruta relativa `~ / program_files / internet / SSH_tunneling / 'se incluye en la variable de entorno PATH, que es insegura en combinación con la acción -execdir de find. Elimine esa input de $ PATH

Tienes ~/program_files/internet/SSH_tunneling/ en tu $PATH . Eso es literal ~ . Eso no significa su directory de inicio . En cambio, eso significa la ruta relativa ~/program_files/internet/SSH_tunneling/ , que es SSH_tunneling dentro de internet dentro de program_files dentro del directory ~ dentro del directory actual.

-execdir no le gustan los directorys relativos en $PATH porque hace chdir() en los directorys donde ejecuta los commands para ejecutar. Por ejemplo, si al descender el tree del directory, find encuentra un file gif en ./some-dir que también contiene un directory ~ , y hay un ./some-dir/~/program_files/internet/SSH_tunneling/basename , entonces puede terminar ejecutando ese basename .

Probablemente tengas un:

 PATH="~/program_files/internet/SSH_tunneling/" 

en su ~/.bash* que debería haber sido:

 PATH=~/program_files/internet/SSH_tunneling/ 

o

 PATH="$HOME/program_files/internet/SSH_tunneling" 
  $ find . -regex ".*t\.gif" | xargs basename basename: extra operand './f10_1t.gif' 

xargs ejecutará el basename con tantos arguments como sea posible. basename espera como máximo 2 arguments, el primero una ruta, el segundo un patrón. Entonces tu command no tiene sentido.

También xargs de forma pnetworkingeterminada, espera un espacio en blanco (espacio, pestaña y posiblemente más dependiendo de su configuration regional y la implementación de find ) y nueva línea (todo lo cual puede ocurrir en nombres de file) en la input con manejo especial de comillas, que no es el formatting de salida por find .

find generará algo así como:

 ./path/to/picture from "The End of the World".gif 

Qué xargs entenderá como 3 arguments diferentes: ./path/to/picture , from , The End of the World.gif . find no tiene modo de salida en el formatting esperado por xargs , aquí:

 ./path/to/picture\ from\ \"The\ End\ of\ the\ World\".gif 

o

 './path/to/picture from "The End of the World".gif' 

Algunas implementaciones de xargs admiten una opción -0 para manejar una list delimitada por NUL en lugar de una línea en blanco / nueva + cita una, y algunas implementaciones de find tienen -print0 pnetworkingicado -print0 para generar nombres de files con ese formatting (en los que no, puedes use -exec printf '%s\0' {} + lugar).

Entonces algo así como:

 find . -name "*t.gif" -print0 | xargs -r0 -I {} basename {} t.gif 

que sería de poca utilidad para su objective general. En cambio, probablemente quieras algo como:

 find . -name '*t.gif' -type f -exec sh -c ' for f do cp "${f%t.gif}.gif" "$f" done' sh {} + 

O con zsh :

 autoload zmv # if not already in ~/.zshrc zmv -C '(**/)(*)t.gif(#qD.)' '$1$2.gif'