Déplacer un fichier et laisser un lien logiciel derrière

10

Je cherche une seule commande linux qui me permette de faire l'équivalent de ceci:

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

S'il n'y en a pas, quelle est la meilleure façon de le faire pour un tas de fichiers?

itsadok
la source
Je ne connais pas assez bien les scripts Bash pour l'écrire, mais ma solution serait d'écrire simplement un script et de l'appeler quelque chose de accrocheur comme cpln
Unkwntech
1
Le cp ne devrait-il pas être mv?
Bart van Heukelom
Non. L'option -f de ln s'en charge.
innaM
1
essayez-le sur un fichier de 10 Go
hayalci
2
@HelloGoodbye Vous confondez &&avec &. Comme écrit, la ligne vérifie la valeur de retour de cp et n'exécute la deuxième partie qu'en cas de succès.
itsadok

Réponses:

7

Une petite remarque est que vous pouvez utiliser ln les deux fois pour que la commande ne déplace pas réellement les données (en supposant que les deux chemins se trouvent sur le même système de fichiers).

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

Mais je suppose que vous voulez déplacer le contenu de / certains / chemin / vers un autre disque, puis créer des liens vers les nouveaux fichiers afin que "personne" ne le remarque.

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

Envelopper dans une fonction bash:

function cpln {
    for f in `ls $1`
    do
        ln $1/$f $2 && ln -sf $2/$f $1
    done
}
Mr Shark
la source
Existe-t-il un moyen de faire fonctionner cela si ce que je déplace se trouve être un répertoire?
tladuke
Comment cela déplace-t-il le fichier réel sur le disque?
Ibrahim
Ibrahim: les données ne bougent pas, elles mettent simplement à jour les pointeurs du répertoire.
M. Shark
tladuke: Oui et non. Puisque le répertoire est beaucoup plus petit sur le disque, il n'y a pas besoin de l'astuce ln (qui ne fonctionne pas pour les répertoires), faites juste un mv :-)
Mr Shark
2

Voici mon script que vous pourriez utiliser (prend deux paramètres / certains / chemin / fichier et / un autre / chemin /):

#!/bin/bash
cp $1 $2
if [ "$?" -ne "0" ]; then
    echo "Some error"
    exit 1
    fi
ln -sf $2/${1##*/} ${1%/*}
Kazimieras Aliulis
la source
Truc cool avec les manipulations de cordes, jamais vu auparavant. Merci!
itsadok
1

Sérieusement, je pensais que c'était une question vraiment facile.

Voici ce que je peux faire 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/");
}

J'espérais quelque chose de plus élégant, mais je suppose que je vais l'utiliser.

itsadok
la source
1
Pour le faire "en Perl", vous devez utiliser File :: Copy (ou similaire) et symlink (). Perl n'est pas un shell; évitez system (), et surtout évitez de passer des lignes de commande entières à system () (par exemple, que faire si un argument contient un espace?). Dans tous les cas, toujours, toujours, vérifiez TOUJOURS les valeurs de retour.
John Siracusa,