Pindahkan file dan ganti dengan symlink

16

Dapatkah seseorang memberi saya perintah yang akan:

  • pindahkan file ke direktori baru
  • dan meninggalkan symlink di lokasi lamanya menuju yang baru
Yo B.
sumber

Jawaban:

19

mvmemindahkan file, dan ln -smembuat tautan simbolis, sehingga tugas dasar diselesaikan oleh skrip yang mengeksekusi dua perintah ini:

#!/bin/sh
mv -- "$1" "$2"
ln -s -- "$2" "$1"

Ada beberapa peringatan. Jika argumen kedua adalah direktori, makamv akan memindahkan file ke direktori itu, tetapi ln -sakan membuat tautan ke direktori daripada ke file yang dipindahkan.

#!/bin/sh
set -e
original="$1" target="$2"
if [ -d "$target" ]; then
  target="$target/${original##*/}"
fi
mv -- "$original" "$target"
ln -s -- "$target" "$original"

Peringatan lain adalah bahwa argumen pertama ln -s adalah teks yang tepat dari tautan simbolik. Ini relatif ke lokasi target, bukan ke direktori tempat perintah dieksekusi. Jika lokasi asli tidak ada di direktori saat ini dan target tidak dinyatakan oleh jalur absolut, tautannya akan salah. Dalam hal ini, jalan harus ditulis ulang. Dalam hal ini, saya akan membuat tautan absolut (tautan relatif akan lebih disukai, tetapi sulit untuk memperbaikinya). Skrip ini mengasumsikan bahwa Anda tidak memiliki nama file yang diakhiri dengan karakter baris baru.

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

Jika Anda memiliki banyak file, proseskan dalam satu lingkaran.

#!/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
Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Terima kasih Gilles, untuk skrip dan penjelasannya. Saya akan mencoba memahami itu!
Yo B.
Ini harus ditandai sebagai jawaban yang benar
Sridhar Sarnobat
Untuk membuat jawaban ini lebih luar biasa, rsync --remove-source-filesmungkin lebih informatif bagi pengguna yang memindahkan file besar dari disk yang mungkin memerlukan waktu.
Sridhar Sarnobat
Saya pikir Anda harus memanggil sh dengan -e sehingga rusak pada kesalahan, misalnya jika Anda menghentikan perintah mv karena file sudah ada
Alex
2

Masukkan ini ke dalam file .sh dan buat itu dapat dieksekusi ( chmod +x filename):

#!/bin/bash

mv "$1" "$2"
ln -s "$2" "$1"

Contoh penggunaan:

./test.sh asdf otherdir/asdf

Perhatikan bahwa ini tidak memeriksa keselamatan, dll. Bergantung pada seberapa kompleks tugas Anda, ini mungkin cukup.

MatthewRock
sumber
Terima kasih Matthew, ini berfungsi dengan baik ketika diterapkan pada satu file. Tapi Anda dapat membantu saya generalisasi ini untuk dua direktori seperti ini: ./test.sh .mozila/firefox/zotero/*/*.pdf MyBbliography/*.pdf. The *tampaknya tidak bisa bekerja sama dengan Anda test.sh. Apakah Anda punya solusinya? Thx
Yo B.
2
Skrip @kadok MatthewRock hanya berfungsi untuk satu file, dan targetnya harus berupa path absolut atau sumbernya harus ada di direktori saat ini.
Gilles 'SO- stop being evil'
Juga, itu tidak akan berfungsi jika $ 1 adalah file tetapi $ 2 adalah direktori.
Sridhar Sarnobat
0

Saya biasanya menggunakan fungsi satu baris ini:

function ml() { mkdir -p "$(dirname "$1")" && rsync -aP --no-links "$1" "$2" && ln -sf "$2" "$1" }

Penggunaannya mirip dengan mv atau cp:

ml old_file target_dir/new_file_name

Hancurkan:

  • mkdir -p "$(dirname "$1")" - buat direktori tujuan jika belum ada
    • dirname "$1" - dapatkan komponen direktori path (strip the filename)
  • rsync -aP --no-links "$1" "$2"- salin file ke tujuan. Ganti ini dengan mv "$1" "$2"jika kedua file berada di sistem file yang sama untuk kinerja yang lebih baik.
    • -a- mempertahankan kepemilikan dan semua izin lainnya. Anda dapat menyetel ini untuk hanya mempertahankan komponen yang Anda inginkan.
    • -P - menunjukkan kemajuan.
    • --no-links - jangan menyalin tautan - ini berarti Anda dapat menjalankan perintah ini sebanyak yang Anda inginkan pada file yang sama, dan Anda tidak akan pernah kehilangan file Anda dengan secara tidak sengaja menimpa file tujuan Anda dengan symlink ke dirinya sendiri.
  • ln -sf "$2" "$1" - menimpa file lama dengan symlink ke file baru
    • -s - Gunakan tautan simbolis
    • -f - Timpa file lama
pengguna60561
sumber