Archivo mv de Linux con nombre largo

19

En Linux a veces renombre archivos como este:

mv dir1/dir2/dir3/file.txt  dir1/dir2/dir3/file.txt.old

Tenga en cuenta que solo quiero cambiar el nombre del archivo, no moverlo a otro directorio.

¿Hay algún comando que me permita hacer una versión abreviada de ese comando? Estoy pensando algo como:

mv dir1/dir2/dir3/file.txt  file.txt.old

o tal vez incluso algo como (solo agregar al nombre):

mv dir1/dir2/dir3/file.txt  {}.old

Mi objetivo no es tener que volver a especificar la ruta completa.

Sé que esos "ejemplos" que escribí no funcionan, pero es solo una idea de lo que quiero lograr.

No quiero tener que cd en el directorio.

santiago arizti
fuente
8
¿Por qué no cambias al directorio? Es rápido y resuelve tu problema.
Michael Hampton
Estoy tratando con muchos subdirectorios desde esta misma ubicación, es más lento si tengo que volver a este directorio principal cada vez
santiago arizti
3
Nadie dijo que tenía que cambiar a otro directorio, solo al que desea.
Michael Hampton
Tenga en cuenta que (cd dir1/dir2/dir3 && exec mv file.txt{,.old})tiene efectivamente el mismo rendimiento que el código sin el subproceso, ya que se execevita fork()durante la invocación del comando externo, por lo que tiene exactamente una bifurcación en ambos sentidos.
Charles Duffy

Respuestas:

45

para un solo archivo intente

mv dir1/dir2/dir3/file.{txt,txt.old}

donde se X{a,b}expande la construcción Xa Xb, puede tener una vista previa usando

echo dir1/dir2/dir3/file.{txt,txt.old}

para ver si se ajusta a tu necesidad.

Nota:

  1. eso para múltiples archivos

    mv dir1/dir2/dir3/file{1,2,3}.{txt,txt.old}
    

es poco probable que se expanda a lo que quieres. (esto se expandirá a una combinación de file.txt file1.txt.old file2.txt ...)

  1. {txt,txt.old}se puede acortar {,.old}según el comentario

  2. si el nombre del directorio no es ambiguo, se puede usar comodín.

    mv *1/*2/d*/*.{,old}
    

para uso de múltiples archivos rename

rename -n s/txt/old.txt/ dir1/dir2/dir3/file*.txt 

soltar -npara tener un cambio de nombre efectivo.

Archemar
fuente
1
bueno, ¡no conocía esta forma de expandirme! gracias
santiago arizti
14
¿ mv dir1/dir2/dir3/file.txt{,.old}No funcionaría también y sería aún más corto?
Josh
3
@ Josh Sí, funciona perfectamente y requiere menos pulsaciones de teclas. Yo uso esta construcción muy regularmente.
rlf
2
es divertido cómo puedes usar el shell de Linux durante años y aún encontrar nuevos trucos todo el tiempo
santiago arizti
Supongo que todos esos "trucos" serían más obvios si hubiera tenido algún entrenamiento formal en el idioma bash, pero he estado aprendiendo lo suficiente para llevarme bien.
santiago arizti
6

El comando renamerenombra todos los archivos coincidentes. Su objetivo principal es cambiar el nombre de varios archivos, pero si la expresión de Perl coincide con un solo archivo, cambiará el nombre de este único archivo. Para detalles y sintaxis específica de distribución por favor lea la página de manual: man rename.

Ejemplo de uso: cambie el nombre de "/path/file.txt" a "/path/file.txt.old":

rename 's/file.txt/file.txt.old/g' /path/file.txt

Notación más corta (gracias a shalomb):

rename 's/$/.old/' /path/file.txt
rename '$_.=".old"' /path/file.txt

Para un uso en seco rename -n.

Se pueden encontrar más ejemplos y detalles en https://thepcspy.com/read/bulk-rename-files-in-ubuntu/

Fabian
fuente
genial, conocía el comando de cambio de nombre, pero nunca supe todo lo que podía hacer, ¡gracias!
santiago arizti
66
Desafortunadamente, diferentes distribuciones de Linux tienen renamecomandos diferentes con un comportamiento completamente diferente.
kasperd
1
Para esta tarea particular de renombrar agregando .oldel nombre de archivo, probablemente sea un poco más conveniente hacer un rename 's/$/.old/' /path/to/file.txtorename '$_.=".old"' /path/to/file.txt
shalomb el
@Fabian: no estaba haciendo trampas, solo apuntaba a la "mano más corta" para lo que parece ser un idioma usado frecuentemente que el OP está buscando :)
shalomb
4

Para un caso único, si no quiero cambiar mi directorio actual, podría usar un sub-shell:

(cd dir1/dir2/dir3/ && mv file.txt file.txt.old)

Debido a que está cddentro del sub-shell, no ha cambiado su directorio en su shell real

Adán
fuente
44
Uso más rápido y seguro && exec mv: de esa manera no intentas cambiar el nombre si cdfalla y execconsume el subshell, evitando así una penalización de rendimiento.
Charles Duffy el
De acuerdo con el && caso de un caso único, como dije, no me preocuparía por el costo del subconjunto (manténgalo simple: poder recordar fácilmente cómo hacerlo es la OMI más importante)
Adam
Yo diría que si va a recordar solo una forma, recordar la manera eficiente ayuda a asegurarse de no tomar la ruta ineficiente en los casos en que importa.
Charles Duffy
4

Me gusta la solución de @ archemar de usar la expansión {}, porque puedes usarla cuando ya has comenzado tu línea de comando. Aquí hay algunas otras posibilidades para completar:

F="dir1/dir2/dir3/file.txt" ; mv "$F" "$F.old"

(las comillas solo son necesarias si tiene espacios u otros caracteres que rompen palabras en el nombre)

mymv() {
    mv "$1/$2" "$1/$3"
}

mymv dir1/dir2/dir3 file.txt file.txt.old
mymv dir5/dir6/dir7 file.txt file.txt.old

Notas:

  • Esta es la sintaxis bash, es posible que esté utilizando otro shell
  • mymv puede ser cualquier cadena razonable, utilicé mymv para "mi movimiento".
  • La definición de la función se puede poner en su .bash_profile

Otro:

cd dir1/dir2/dir3 ; mv file.txt file.txt.old ; cd -

pero

(cd dir1/dir2/dir3/ && exec mv file.txt file.txt.old)

(de @Adam y @CharlesDuffy) es posiblemente mejor en caso de que el CD falle.

Ley29
fuente
1
No lo use mmv, ya hay un programa llamado de esta manera.
glglgl
1
@glglgl Hecho :)
Ley29
2

Si desea ingresar al subdirectorio para acortar el mvcomando, pero luego desea regresar al directorio actual, hay dos formas de hacerlo. Una es poner el cdy mven una subshell (como ya se ha sugerido).

El otro es usar pushdy popdcambiar directorios:

pushd dir1/dir2/dir3/; mv file.txt file.txt.old; popd

El pushdcomando es similar cd, excepto que primero inserta el nombre del directorio actual en una pila. popdelimina el nombre superior de la pila y cambia a ese directorio.

AndyB
fuente
pushdy popdson extensiones destinadas a uso interactivo: POSIX las enumera explícitamente como "resultados no especificados", y un shell creado para ejecutar scripts (es decir, en un entorno embebido mínimo) no necesita ser compatible.
Charles Duffy
2

Yo solo haría

cd dir1/dir2/dir3/
mv file.txt file.txt.old
cd ~- # go to the most recent directory
glglgl
fuente
0

La solución que implica: mv something{.txt,.txt.old}está utilizando un "bashismo". Si desea una forma más portátil, utilizando manipulaciones de variables comunes:

# rename all files "file*.txt" of directory /dir1/dir2/dir3 into file*.txt.old:
for f in dir1/dir2/dir3/file*.txt ; do
  mv "$f" "${f/.txt/.txt.old}"  # note there are no terminating "/"
done


# "${var/A/B}" is the content of var with the first occurence of "A" replaced by "B"
Olivier Dulac
fuente
2
Ver pubs.opengroup.org/onlinepubs/009695399/utilities/… para la especificación POSIX pertinente: ${var/text/replacement}es un bashismo en sí mismo.
Charles Duffy el
@CharlesDuffy oh ... Me pones triste :(
Olivier Dulac