Hay alguna maneracon solo el comando buscaranteponer una cadena a los nombres de archivos?
Para que esto:
201a.txt
201b.png
...
Se convierte en esto:
foo_201a.txt
foo_201b.png
...
Este:
find . -name '201*' -execdir mv {} foo_{} \;
No funciona porque la {}
parte incluye el principio ./
del nombre del archivo y, por lo tanto, intenta escribir en foo_./201*
.
Si esto no es posible solo con buscar, ¿cuál es la forma más portátil (léase: solo coreutils, sin scripts de shell, más fácil de entender) de anteponer una cadena a los nombres de archivos?
Respuesta1
No. Pero el rename
comando ofrece una solución sencilla.
$ ls -1
201a.txt
201b.png
$ rename 201 foo_201 201*
$ ls -1
foo_201a.txt
foo_201b.png
$
Respuesta2
Qué tal si
find . -name '201*' -execdir basename {} \; | xargs -I{} mv {} foo_{}
basename
es proporcionado por coreutils
y desde que xargs
lo proporciona findutils
debe ser al menos tan portátil como find -execdir
él mismo.
Alternativamente, usar solo funciones de shell POSIX
find . -name '201*' -execdir sh -c 'mv "$1" "foo_${1#*/}"' sh {} \;
Respuesta3
Esto no es posible find
solo, ni siquiera con GNU find. GNU find puede imprimir archivos sin el prefijo de la línea de comando y colocando otro prefijo en su lugar, usando -printf foo_%p
en lugar de -print
, pero no hay nada similar para -exec
.
(Puedes usar find -printf 'mv foo_%p …' | sh
, si te gusta vivir peligrosamente. Esto solo funciona con nombres de archivos "dóciles" y se rompe terriblemente si hay espacios, comillas y otros caracteres especiales en los nombres de los archivos. Así que no hagas esto).
La forma estándar de hacer esto (de una manera que funciona en cualquier sistema POSIX, y también de una manera común) es llamar a un shell para realizar la manipulación de la cadena.
find . -name '201*' -exec sh -c 'mv -- "$0" "${0%/*}/foo_${0##*/}"' {} \;
No lo uso -execdir
porque es una extensión GNU y pediste portabilidad. Tenga en cuenta que {}
se pasa al shell como argumento. Nunca lo use {}
dentro del código de shell: no solo porque no es portátil, sino más importantemente porque haría que el nombre del archivo se interprete como código de shell, lo que falla si el nombre del archivo contiene caracteres especiales.
En los sistemas POSIX modernos (cualquier cosa de la última década), puede acelerar un poco este comando agrupando las llamadas al shell.
find . -name '201*' -exec sh -c 'for x do mv -- "$x" "${x%/*}/foo_${x##*/}"; done' sh {} +
Alternativamente, en ksh, bash o zsh, puedes usar globbing recursivo en lugar de llamar a find
.
set -o globstar # ksh only
shopt -s globstar # bash only
for x in **/201*; do
mv -- "$x" "${x%/*}/foo_${x##*/}"
done
Respuesta4
Podrías usar un asterisco ( *
) en su lugar, lo que elimina la ./
parte:
find * -name '201*' -exec mv {} foo_{} \;