ver lista ejemplos contenido completa comandos comando basicos archivo linux bash command-line

lista - ls linux



La forma más corta de intercambiar dos archivos en bash (15)

¿Se pueden intercambiar dos archivos en bash?

O, pueden ser intercambiados de una manera más corta que esto:

cp old tmp cp curr old cp tmp curr rm tmp


¿Realmente quieres intercambiarlos? Creo que vale la pena mencionar que se puede hacer una copia de seguridad del archivo sobrescrito automáticamente con mv:

mv new old -b

obtendrás:

old and old~

si quieres tener

old and old.old

puedes usar -S para cambiar ~ a tu sufijo personalizado

mv new old -b -S .old ls old old.old

Con este enfoque, puedes intercambiarlos más rápido, usando solo 2 mv:

mv new old -b && mv old~ new


Agrega esto a tu .bashrc:

function swap() { local TMPFILE=tmp.$$ mv "$1" $TMPFILE mv "$2" "$1" mv $TMPFILE "$2" }

Si desea manejar una falla potencial de las operaciones de mv intermedias, verifique la respuesta de Can Bal .

Tenga en cuenta que ni esta, ni otras respuestas proporcionan una solución atómica , porque es imposible implementar tales sistemas de Linux y / o sistemas de archivos populares de Linux. Para el núcleo de Darwin, verifique el exchangedata datos.


Aquí hay un script de swap con comprobación de errores paranoicos para evitar el improbable caso de una falla.

  • si alguna de las operaciones falla, se informa.
  • la ruta del primer argumento se usa para la ruta temporal (para evitar moverse entre sistemas de archivos) .
  • en el improbable caso de que el segundo movimiento falle, el primero se restaura.

Guión:

#!/bin/sh if [ -z "$1" ] || [ -z "$2" ]; then echo "Expected 2 file arguments, abort!" exit 1 fi if [ ! -z "$3" ]; then echo "Expected 2 file arguments but found a 3rd, abort!" exit 1 fi if [ ! -f "$1" ]; then echo "File ''$1'' not found, abort!" exit 1 fi if [ ! -f "$2" ]; then echo "File ''$2'' not found, abort!" exit 1 fi # avoid moving between drives tmp=$(mktemp --tmpdir=$(dirname $1)) if [ $? -ne 0 ]; then echo "Failed to create temp file, abort!" exit 1 fi # Exit on error, mv $1 $tmp if [ $? -ne 0 ]; then echo "Failed to to first file ''$1'', abort!" rm $tmp exit 1 fi mv $2 $1 if [ $? -ne 0 ]; then echo "Failed to move first file ''$2'', abort!" # restore state mv $tmp $1 if [ $? -ne 0 ]; then echo "Failed to move file, (unable to restore) ''$1'' has been left at ''$tmp''!" fi exit 1 fi mv $tmp $2 if [ $? -ne 0 ]; then # this is very unlikely! echo "Failed to move file, (unable to restore) ''$1'' has been left at ''$tmp'', ''$2'' as ''$1''!" exit 1 fi


Combinando las mejores respuestas, puse esto en mi ~ / .bashrc:

function swap() { tmpfile=$(mktemp $(dirname "$1")/XXXXXX) mv "$1" "$tmpfile" && mv "$2" "$1" && mv "$tmpfile" "$2" }


Esto es lo que uso como comando en mi sistema ( $HOME/bin/swapfiles ). Creo que es relativamente resistente a la maldad.

#!/bin/bash if [ "$#" -ne 2 ]; then me=`basename $0` echo "Syntax: $me <FILE 1> <FILE 2>" exit -1 fi if [ ! -f $1 ]; then echo "File ''$1'' does not exist!" fi if [ ! -f $2 ]; then echo "File ''$2'' does not exist!" fi if [[ ! -f $1 || ! -f $2 ]]; then exit -1 fi tmpfile=$(mktemp $(dirname "$1")/XXXXXX) if [ ! -f $tmpfile ]; then echo "Could not create temporary intermediate file!" exit -1 fi # move files taking into account if mv fails mv "$1" "$tmpfile" && mv "$2" "$1" && mv "$tmpfile" "$2"


La idea de Hardy fue lo suficientemente buena para mí. Así que he intentado mis dos archivos siguientes para intercambiar "sendms.properties", "sendms.properties.swap". Pero una vez que llamé a esta función como el mismo argumento "sendms.properties", este archivo se eliminó. Evitando este tipo de FALLO, agregué una línea para mí :-)

function swp2file() { if [ $1 != $2 ] ; then local TMPFILE=tmp.$$ mv "$1" $TMPFILE mv "$2" "$1" mv $TMPFILE "$2" else echo "swap requires 2 different filename" fi }

Gracias de nuevo Hardy ;-)


Seguramente mv lugar de cp ?


Tengo esto en un guión de trabajo que entregué. Está escrito como una función, pero lo invocarías.

d_swap lfile rfile

El mv de GNU tiene los conmutadores -b y -T. Puedes lidiar con directorios usando el interruptor -T.

Las citas son para nombres de archivos con espacios.

Es un poco detallado, pero lo he usado muchas veces con archivos y directorios. Puede haber casos en los que desee cambiar el nombre de un archivo con el nombre que tenía un directorio, pero esta función no lo controla.

Esto no es muy eficiente si todo lo que quiere hacer es cambiar el nombre de los archivos (dejándolos donde están), eso se hace mejor con una variable de shell.

d_swap() { test $# -eq 2 || return 2 test -e "$1" || return 3 test -e "$2" || return 3 if [ -f "$1" -a -f "$2" ] then mv -b "$1" "$2" && mv "$2"~ "$1" return 0 fi if [ -d "$1" -a -d "$2" ] then mv -T -b "$1" "$2" && mv -T "$2"~ "$1" return 0 fi return 4 }

Esta función cambiará el nombre de los archivos. Utiliza un nombre temporal (coloca un punto ''.'' Delante del nombre) en caso de que los archivos / directorios estén en el mismo directorio, que suele ser el caso.

d_swapnames() { test $# -eq 2 || return 2 test -e "$1" || return 3 test -e "$2" || return 3 local lname="$(basename "$1")" local rname="$(basename "$2")" ( cd "$(dirname "$1")" && mv -T "$lname" ".${rname}" ) && / ( cd "$(dirname "$2")" && mv -T "$rname" "$lname" ) && / ( cd "$(dirname "$1")" && mv -T ".${rname}" "$rname" ) }

Eso es mucho más rápido (no hay copia, solo cambio de nombre). Es aún más feo. Y renombrará cualquier cosa: archivos, directorios, tuberías, dispositivos.


Una versión algo endurecida que funciona tanto para archivos como para directorios:

function swap() { if [ ! -z "$2" ] && [ -e "$1" ] && [ -e "$2" ] && ! [ "$1" -ef "$2" ] && (([ -f "$1" ] && [ -f "$2" ]) || ([ -d "$1" ] && [ -d "$2" ])) ; then tmp=$(mktemp -d $(dirname "$1")/XXXXXX) mv "$1" "$tmp" && mv "$2" "$1" && mv "$tmp"/"$1" "$2" rmdir "$tmp" else echo "Usage: swap file1 file2 or swap dir1 dir2" fi }

Esto funciona en Linux. No estoy seguro de OS X.


Uno de los problemas que tuve al utilizar cualquiera de las soluciones que se proporcionan aquí: los nombres de sus archivos se cambiarán.

Incorporé el uso de basename y dirname para mantener los nombres de archivo intactos *.

swap() { if (( $# == 2 )); then mv "$1" /tmp/ mv "$2" "`dirname $1`" mv "/tmp/`basename $1`" "`dirname $2`" else echo "Usage: swap <file1> <file2>" return 1 fi }

He probado esto en bash y zsh.

* Para aclarar cómo es mejor:

Si comienzas con:

dir1/file2: this is file2 dir2/file1: this is file1

Las otras soluciones terminarían con:

dir1/file2: this is file1 dir2/file1: this is file2

Los contenidos se intercambian pero los nombres de los archivos permanecen . Mi solución lo hace:

dir1/file1: this is file1 dir2/file2: this is file2

Se intercambian los contenidos y nombres.



el uso de mv significa que tiene una operación menos, no se necesita el rm final, también mv solo está cambiando las entradas del directorio, por lo que no está utilizando espacio de disco adicional para la copia.

Entonces, Temptationh es implementar una función de shell swap () o algo similar. Si es extremadamente cuidadoso verifica los códigos de error. Podría ser terriblemente destructivo. También es necesario comprobar el archivo tmp preexistente.


$ mv old tmp && mv curr old && mv tmp curr

¡Es un poco más eficiente!

Envuelto en la función de shell reutilizable:

function swap() { local TMPFILE=tmp.$$ mv "$1" $TMPFILE && mv "$2" "$1" && mv $TMPFILE $2 }


mv old tmp mv curr old mv tmp curr


tmpfile=$(mktemp $(dirname "$file1")/XXXXXX) mv "$file1" "$tmpfile" mv "$file2" "$file1" mv "$tmpfile" "$file2"