Odpowiedzi:
mv
przenosi plik i ln -s
tworzy dowiązanie symboliczne, więc podstawowe zadanie wykonuje skrypt, który wykonuje te dwa polecenia:
#!/bin/sh
mv -- "$1" "$2"
ln -s -- "$2" "$1"
Jest kilka zastrzeżeń. Jeśli drugim argumentem jest katalog, mv
przenosi plik do tego katalogu, ale ln -s
tworzy łącze do katalogu, a nie do przeniesionego pliku.
#!/bin/sh
set -e
original="$1" target="$2"
if [ -d "$target" ]; then
target="$target/${original##*/}"
fi
mv -- "$original" "$target"
ln -s -- "$target" "$original"
Innym zastrzeżeniem jest to, że pierwszym argumentem ln -s
jest dokładny tekst dowiązania symbolicznego. Jest to zależne od położenia celu, a nie katalogu, w którym polecenie jest wykonywane. Jeśli oryginalnej lokalizacji nie ma w bieżącym katalogu, a cel nie jest wyrażony przez ścieżkę bezwzględną, link będzie niepoprawny. W takim przypadku ścieżka musi zostać przepisana. W takim przypadku utworzę link bezwzględny (preferowany byłby link względny, ale trudniej jest go poprawnie uzyskać). Ten skrypt zakłada, że nie masz nazw plików, które kończą się znakiem nowej linii.
#!/bin/sh
set -e
original="$1" target="$2"
if [ -d "$target" ]; then
target="$target/${original##*/}"
fi
mv -- "$original" "$target"
case "$original" in
*/*)
case "$target" in
/*) :;;
*) target="$(cd -- "$(dirname -- "$target")" && pwd)/${target##*/}"
esac
esac
ln -s -- "$target" "$original"
Jeśli masz wiele plików, przetwarzaj je w pętli.
#!/bin/sh
while [ $# -gt 1 ]; do
eval "target=\${$#}"
original="$1"
if [ -d "$target" ]; then
target="$target/${original##*/}"
fi
mv -- "$original" "$target"
case "$original" in
*/*)
case "$target" in
/*) :;;
*) target="$(cd -- "$(dirname -- "$target")" && pwd)/${target##*/}"
esac
esac
ln -s -- "$target" "$original"
shift
done
rsync --remove-source-files
może być bardziej pouczająca dla użytkowników, którzy przenoszą duży plik z dysku, co może zająć trochę czasu.
Umieść to w pliku .sh i uczyń go wykonywalnym ( chmod +x filename
):
#!/bin/bash
mv "$1" "$2"
ln -s "$2" "$1"
Przykład użycia:
./test.sh asdf otherdir/asdf
Pamiętaj, że nie wymaga to kontroli bezpieczeństwa itp. W zależności od stopnia złożoności zadania może to być wystarczające.
./test.sh .mozila/firefox/zotero/*/*.pdf MyBbliography/*.pdf
. *
Nie wydają się być pracy z test.sh
. Czy masz obejście? Thx
Ogólnie używam tej funkcji jednowierszowej:
function ml() { mkdir -p "$(dirname "$1")" && rsync -aP --no-links "$1" "$2" && ln -sf "$2" "$1" }
Użycie jest podobne do mv lub cp:
ml old_file target_dir/new_file_name
Podział:
mkdir -p "$(dirname "$1")"
- utwórz katalog docelowy, jeśli jeszcze nie istnieje
dirname "$1"
- pobierz komponent katalogu ścieżki (usuń nazwę pliku)rsync -aP --no-links "$1" "$2"
- skopiuj plik do miejsca docelowego. Zastąp to, mv "$1" "$2"
jeśli oba pliki znajdują się w tym samym systemie plików, aby uzyskać lepszą wydajność.
-a
- zachować własność i wszystkie inne uprawnienia. Możesz to dostroić, aby zachować tylko te elementy, które chcesz.-P
- pokaż postęp.--no-links
- nie kopiuj linków - oznacza to, że możesz uruchomić tę komendę tyle razy, ile chcesz na tym samym pliku, i nigdy nie stracisz pliku, przypadkowo zastępując plik docelowy dowiązaniem symbolicznym do siebie.ln -sf "$2" "$1"
- nadpisz stary plik dowiązaniem symbolicznym do nowego pliku
-s
- używaj dowiązań symbolicznych-f
- nadpisz stary plik