移动文件并用符号链接替换


16

有人可以给我一个命令,该命令将:

  • 将文件移到新目录
  • 并在旧位置向新位置留一个符号链接

Answers:


19

mv移动文件并ln -s创建符号链接,因此基本任务是通过执行以下两个命令的脚本来完成的:

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

有一些警告。如果第二个参数是目录,则会mv将文件移至该目录,但ln -s会创建指向该目录的链接,而不是指向已移动文件的链接。

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

另一个需要注意的是,第一个参数ln -s是符号链接的确切文本。它是相对于目标位置的,而不是相对于执行命令的目录。如果原始位置不在当前目录中,并且目标没有由绝对路径表示,则链接将不正确。在这种情况下,需要重写路径。在这种情况下,我将创建一个绝对链接(相对链接会更可取,但更难做到正确)。该脚本假定您没有以换行符结尾的文件名。

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

如果您有多个文件,请循环处理它们。

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

1
感谢Gilles,感谢您提供脚本和解释。我会尽力理解的!
Yo B.

这应该标记为正确的答案
Sridhar Sarnobat '16

要使此答案更加出色,rsync --remove-source-files可能对从磁盘上移出大文件的用户可能会花费一些时间提供更多信息。
Sridhar Sarnobat '16

我认为您应该使用-e调用sh,这样它就可以在错误时中断,例如,如果由于文件已存在而停止了mv命令
Alex

2

将其放在.sh文件中并使其可执行(chmod +x filename):

#!/bin/bash

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

用法示例:

./test.sh asdf otherdir/asdf

请注意,这不会进行安全检查等。根据您的任务复杂程度,这可能就足够了。


谢谢Matthew,将它应用于一个文件时,它可以完美工作。但是你能帮我概括如下两个目录吗 ./test.sh .mozila/firefox/zotero/*/*.pdf MyBbliography/*.pdf?本*似乎并不与你的工作test.sh。您有解决方法吗?Thx
Yo B.

2
@kadok MatthewRock的脚本仅适用于单个文件,目标必须是绝对路径,否则源必须在当前目录中。
吉尔(Gilles)'所以

另外,如果$ 1是文件,而$ 2是目录,则它将不起作用。
Sridhar Sarnobat '16

0

我通常使用此单行函数:

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

用法类似于mv或cp:

ml old_file target_dir/new_file_name

分解:

  • mkdir -p "$(dirname "$1")" -创建目标目录(如果尚不存在)
    • dirname "$1" -获取路径的目录部分(带文件名)
  • rsync -aP --no-links "$1" "$2"-将文件复制到目标位置。mv "$1" "$2"如果两个文件都在同一文件系统上,则用替换为更好的性能。
    • -a-保留所有权和所有其他权限。您可以对其进行调整以仅保留所需的组件。
    • -P -显示进度。
    • --no-links -不要复制链接-这意味着您可以在同一文件上多次运行此命令,并且永远不会因使用符号链接自身意外覆盖目标文件而丢失文件。
  • ln -sf "$2" "$1" -用符号链接覆盖旧文件到新文件
    • -s -使用符号链接
    • -f -覆盖旧文件
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.