【问题标题】:How do I move a relative symbolic link?如何移动相对符号链接?
【发布时间】:2012-01-21 07:55:19
【问题描述】:

我有很多相关的符号链接想要移动到另一个目录。

如何在保留正确路径的同时移动符号链接(具有相对路径的链接)?

【问题讨论】:

  • 您仍然希望链接在移动时具有符号性吗?这会影响您将获得的答案。
  • 您还希望链接指向相对路径,还是将它们更改为绝对路径好吗?
  • 我认为这属于 unix.stackexchange.com,尽管 superuser.com 也可以。
  • @fgr 是的,我想保留相对符号链接,例如 ../../dir/sym 将更改为 ../../../dir/sym

标签: linux perl shell unix symlink


【解决方案1】:

您可以使用readlink -f foo 将相对路径转换为完整路径。所以你会做这样的事情:

ln -s $(readlink -f $origlink) $newlink
rm $origlink

编辑:

我注意到您希望保持路径相对。在这种情况下,移动链接后,您可以使用symlinks -c 将绝对路径转换回相对路径。

【讨论】:

  • 您也可以使用ln-r 选项让它创建一个相对链接,即ln -sr "$(readlink -f "$origlink")" "$newlink"; rm "$origlink"
  • 注意:如果origlink不存在,则创建垃圾链接。
  • 你应该正确引用ln -rs "$(readlink -f "$origlink")" "$newlink"
  • 如果您没有可用的symlinks 实用程序,您可以使用ln-r 选项将现有的绝对符号链接转换为相对符号链接。 ln -srf $newlink。或者只是按照@Robin479 的建议,在第一步中创建一个相对符号链接。
  • Mac OS 上readlink 没有-f 选项,因此您必须使用brew install coreutils 并改用greadlink
【解决方案2】:

这是一个保留相对路径的perl 解决方案:

use strictures;
use File::Copy qw(mv);
use Getopt::Long qw(GetOptions);
use Path::Class qw(file);
use autodie qw(:all GetOptions mv);

my $target;
GetOptions('target-directory=s' => \$target);
die "$0 -t target_dir symlink1 symlink2 symlink3\n" unless $target && -d $target;

for (@ARGV) {
    unless (-l $_) {
        warn "$_ is not a symlink\n";
        next;
    }
    my $newlink = file(readlink $_)->relative($target)->stringify;
    unlink $_;
    symlink $newlink, $_;
    mv $_, $target;
}

【讨论】:

    【解决方案3】:

    可以使用tar 移动包含相关符号链接的文件夹。

    例如:

    cd folder_to_move/..
    tar czvf files.tgz folder_to_move
    cd dest_folder/..
    tar xzvf /absolute/path/to/folder_to_move/../files.tgz
    
    # If all is fine, clean-up
    rm /absolute/path/to/folder_to_move/../files.tgz
    rm -rf /absolute/path/to/folder_to_move
    

    【讨论】:

    • 甚至可以使用 tar 管道链在一个命令中完成所有操作 cd folder_to_move; tar cf - . | (cd /usr/local/dest_folder; tar xf -)
    • 这似乎对我不起作用。 'tar' 究竟如何以及何时重写相关符号链接?
    【解决方案4】:

    当然使用ln

    for i in *; do # or whatever pattern you're wanting to match
        ln -sr "$(readlink "$i")" newdir/"$i";
    done;
    

    我很惊讶这能奏效,但LN(1) 必须足够聪明,才能注意到正在发生的事情并帮助你!我什至用../somethingelse(在链接重写中应该是一个无操作)和..(这将从链接目标中删除..)的“newdir”来尝试它,它工作得非常好.

    【讨论】:

      【解决方案5】:

      改进 Christopher Neylan 的回答:

      ~/bin $ cat mv_ln
      #!/bin/bash
      #
      # inspired by https://stackoverflow.com/questions/8523159/how-do-i-move-a-relative-symbolic-link#8523293
      #          by Christopher Neylan
      
      help() {
         echo 'usage: mv_ln src_ln dest_dir'
         echo '       mv_ln --help'
         echo
         echo '  Move the symbolic link src_ln into dest_dir while'
         echo '  keeping it relative'
         exit 1
      }
      
      [ "$1" == "--help" ] || [ ! -L "$1" ] || [ ! -d "$2" ] && help
      
      set -e # exit on error
      
      orig_link="$1"
      orig_name=$( basename    "$orig_link" )
      orig_dest=$( readlink -f "$orig_link" )
      dest_dir="$2"
      
      ln -r -s "$orig_dest" "$dest_dir/$orig_name"
      rm "$orig_link"
      

      这也是https://github.com/tpo/little_shell_scripts的一部分

      【讨论】:

      • 你忘记了$(…)周围的一些引号
      • @ctrl-alt-delor - 请举例说明$( ) 的缺失引用会产生负面/意外影响吗?
      • 在从orig_link="$1" 中丢失它们的相同情况下。我只是做了一些测试,但我无法打破它,可能是我只是出于习惯,因为我发现记住一个避免错误的简单规则比一组许多规则更容易。跨度>
      • 分配给变量时不需要引号。不是一个坏习惯,但没有必要。
      猜你喜欢
      • 2019-04-04
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-03
      • 2019-04-15
      • 1970-01-01
      相关资源
      最近更新 更多