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.
Usted podría simplemente moverlos, en lugar de hacer una copia.
#!/bin/sh
# Created by Wojtek Jamrozy (www.wojtekrj.net)
mv $1 cop_$1
mv $2 $1
mv cop_$1 $2
http://www.wojtekrj.net/2008/08/bash-script-to-swap-contents-of-files/
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"