Przenieś plik i zostaw miękki link za sobą

10

Szukam pojedynczego polecenia linux, które pozwoli mi zrobić równoważne z tym:

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

Jeśli nie ma, jaki jest najlepszy sposób na zrobienie tego dla wielu plików?

itsadok
źródło
Nie znam skryptów Bash wystarczająco dobrze, aby je napisać, ale moim rozwiązaniem byłoby po prostu napisanie skryptu i nazwanie go czymś chwytliwym jak cpln
Unkwntech
1
Czy CP nie powinien być mv?
Bart van Heukelom
Nie. Zajmuje się tym opcja -f dla ln.
innaM
1
wypróbuj go na pliku 10 GB
hayalci
2
@HelloGoodbye pan myli &&się &. Jak napisano, linia sprawdza wartość zwracaną cp i uruchamia drugą część, jeśli się powiedzie.
itsadok

Odpowiedzi:

7

Mała uwaga: możesz użyć ln dwa razy, aby polecenie faktycznie nie przenosiło danych (zakładając, że obie ścieżki znajdują się w tym samym systemie plików).

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

Zakładam jednak, że chcesz przenieść zawartość / some / path / na inny dysk, a następnie utworzyć łącza do nowych plików, aby nikt nie zauważył.

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

Zawijanie go w funkcję bash:

function cpln {
    for f in `ls $1`
    do
        ln $1/$f $2 && ln -sf $2/$f $1
    done
}
Pan Shark
źródło
Czy istnieje sposób, aby to zadziałało, jeśli to, co przenoszę, to katalog?
tladuke
Jak to przenosi rzeczywisty plik na dysk?
Ibrahim,
Ibrahim: dane się nie przenoszą, po prostu aktualizują wskaźniki w katalogu.
Pan Shark,
tladuke: Tak i nie. Ponieważ katalog jest znacznie mniejszy na dysku, sztuczka ln (która nie działa w przypadku katalogów) nie jest potrzebna, po prostu zrób mv :-)
Mr Shark,
2

Jest mój skrypt, którego możesz użyć (pobiera dwa parametry / some / path / file i / another / path /):

#!/bin/bash
cp $1 $2
if [ "$?" -ne "0" ]; then
    echo "Some error"
    exit 1
    fi
ln -sf $2/${1##*/} ${1%/*}
Kazimieras Aliulis
źródło
Fajna sztuczka z manipulacjami strunami, nigdy wcześniej tego nie widziałam. Dzięki!
itsadok
1

Poważnie, myślałem, że to było naprawdę łatwe pytanie.

Oto, co mogę zrobić w Perlu:

#!/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/");
}

Miałem nadzieję na coś bardziej eleganckiego, ale chyba tego użyję.

itsadok
źródło
1
Aby to zrobić „w Perlu”, należy użyć File :: Copy (lub podobnego) i symlink (). Perl nie jest powłoką; Unikaj system (), a zwłaszcza unikaj przekazywania całych linii poleceń do system () (np. co jeśli argument zawiera spację?). Tak czy inaczej, zawsze, zawsze ZAWSZE sprawdzaj zwracane wartości.
John Siracusa