Mueva un archivo y deje un enlace suave detrás

10

Estoy buscando un solo comando de Linux que me permita hacer el equivalente de esto:

cp /some/path/file /another/path/ && ln -sf /another/path/file /some/path/

Si no hay uno, ¿cuál es la mejor manera de hacer esto para un montón de archivos?

itsadok
fuente
No sé Bash scripting suficientemente bien como para escribirlo, pero mi solución sería simplemente escribir un guión y lo llaman algo pegadizo como CPLN
Unkwntech
1
¿No debería cp ser mv?
Bart van Heukelom
No. La opción -f de ln se encarga de eso.
INNAM
1
probarlo en un archivo de 10 GB
hayalci
2
@HelloGoodbye Estás confundiendo &&con &. Tal como está escrito, la línea verifica el valor de retorno de cp y solo ejecuta la segunda parte si tuvo éxito.
itsadok

Respuestas:

7

Una pequeña nota es que puede usar ln ambas veces para hacer que el comando no mueva los datos (suponiendo que ambas rutas estén en el mismo sistema de archivos).

ln /some/path/file /another/path/ && ln -sf /another/path/file /some/path/

Pero supongo que desea mover el contenido de / some / path / a otro disco y luego crear enlaces a los nuevos archivos para que "nadie" se dé cuenta.

for f in `ls /some/path/`; do ln /some/path/$f /another/path/ && ln -sf /another/path/$f /some/path; done

Envolviéndolo en una función bash:

function cpln {
    for f in `ls $1`
    do
        ln $1/$f $2 && ln -sf $2/$f $1
    done
}
Señor tiburón
fuente
¿Hay alguna manera de hacer que esto funcione si lo que estoy moviendo es un directorio?
tladuke
¿Cómo mueve esto el archivo real en el disco?
Ibrahim
Ibrahim: los datos no se mueven, solo actualizan los punteros en el directorio.
Mr Shark
Tladuke: Sí y no. Dado que el directorio es mucho más pequeño en el disco, no hay necesidad del truco ln (que no funciona para los directores), solo haga un mv :-)
Mr Shark
2

Hay mi script que podría usar (toma dos parámetros / some / path / file y / another / path /):

#!/bin/bash
cp $1 $2
if [ "$?" -ne "0" ]; then
    echo "Some error"
    exit 1
    fi
ln -sf $2/${1##*/} ${1%/*}
Kazimieras Aliulis
fuente
Genial truco con las manipulaciones de cuerdas, nunca antes había visto eso. ¡Gracias!
itsadok
1

En serio, pensé que esta era una pregunta realmente fácil.

Esto es lo que puedo hacer en perl:

#!/bin/perl
# Usage: cpln TARGETDIR SOURCE...
# Example: find tree/ -type f | xargs cpln commands/

$target = shift;

foreach(@ARGV) {
    m[(.*)/([^/]+)];
    system("cp $_ $target");
    system("ln -sf $target/$2 $1/");
}

Esperaba algo más elegante, pero supongo que lo usaré.

itsadok
fuente
1
Para hacerlo "en Perl", debe usar File :: Copy (o similar) y symlink (). Perl no es concha; evitar system (), y especialmente evitar pasar líneas de comando completas a system () (por ejemplo, ¿qué pasa si un argumento contiene un espacio?). De cualquier manera, siempre, siempre, SIEMPRE verifique los valores de retorno.
John Siracusa