如何“重新链接”大量损坏的符号链接?

如何“重新链接”大量损坏的符号链接?

我有一个目录树,其中有一堆指向文件的符号链接/home...但是,我已经转移/home/mnt/home并需要一种方法来“重新链接”所有符号链接。是否存在这样的功能或者我需要编写脚本来执行此操作?

作为一个例子,我有类似以下内容:

[root@trees ~]# ls -l /mnt/home/someone/something
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/e

/mnt/home/someone/something/subdir:
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/subdir/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/subdir/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/subdir/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/subdir/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/subdir/e

我想要一个命令,它将找到所有符号链接并重新链接到相同的位置,但在下面/mnt/home而不是/home

存在这样的命令吗?

答案1

没有命令可以重定向符号链接,您所能做的就是删除它并创建另一个。假设您有 GNU 实用程序(例如,在非嵌入式 Linux 或 Cygwin 下),您可以使用主要-lname的 来find按目标匹配符号链接,并readlink读取链接的内容。未经测试:

find /mnt/home/someone/something -lname '/home/someone/*' \
     -exec sh -c 'ln -snf "/mnt$(readlink "$1")" "$1"' sh {} \;

最好使这些符号链接具有相对性。假设ln来自 GNU coreutils 8.22,只需将该-r选项传递ln给其他选项,它就会将目标转换为相对路径。对于较旧的系统或批量重写有效链接,有一个方便的小实用程序,称为symlinks(最初由 Mark Lord,现在由 J. Brandt Buckley 维护),存在于许多 Linux 发行版中。

在移动之前,或者在如上所述恢复有效链接之后,运行symlinks -c /mnt/home/someone/something将指定目录下的所有绝对符号链接转换为相对符号链接,除非它们跨越文件系统边界。

答案2

我知道这并不完全是作者所要求的,但似乎他们已经有了答案,所以我为像我这样偶然发现这个问题的其他人添加这个答案。

如果需要更灵活的解决方案,例如有一堆损坏的符号链接,可以通过替换部分符号链接的目标来修复,以下内容应该会有所帮助。

例如。更改用户名后,在移动完成后,在许多链接的目标中用新用户名替换旧用户名。创建一个名为replace-simlinks 的脚本,如下所示:

#!/bin/bash
link=$1
# grab the target of the old link
target=$(readlink -- "$1")

# replace the first occurrence of oldusername with newusername in the target string
target=${target/oldusername/newusername}

# Test the link creation
echo ln -s -- "$target" "$link"

# If the above echo shows the correct commands are being issued, then uncomment the following lines and run the command again
#rm "$link"
#ln -s "$target" "$link"

并使用以下命令调用它:

find /home/newusername/ -lname '/home/oldusername/*' -exec ~/bin/replace-simlinks {} \;

希望这对某人有帮助

编辑:感谢 Gilles 启动此脚本以及有关使用符号链接脚本使链接相对的提示。

答案3

创建/home为 的符号链接/mnt/home,所有现有符号链接将再次有效。

答案4

我写了一个fix_broken_symlinksbash脚本工具:

我希望它能成为流行的 的配套工具symlinks,它可以做一些其他有用的事情。

这是我的工具:

# find all broken symlinks
fix_broken_symlinks path/to/dir

# dry-run fix them
fix_broken_symlinks path/to/dir find_regex replacement_str

# actually fix them (passing `-f` to force it)
fix_broken_symlinks path/to/dir find_regex replacement_str -f

我付出了很多努力来获得非常漂亮且一致的输出。

运行示例:

/home/gabriel/GS/dev/RESEARCH$ fix_broken_symlinks . '/home/gabriel/GS/dev' '/home/gabriel/GS/dev/RESEARCH' -f
4 broken symlinks found!

************************************************************************
'--force' is on! Writing new **relative** symlinks!
************************************************************************

    1/4:    BROKEN: './lldb/Link to Debuggers_General' -> '/home/gabriel/GS/dev/Debuggers_General'
            FIXED : './lldb/Link to Debuggers_General' -> '/home/gabriel/GS/dev/RESEARCH/Debuggers_General'
            FINAL : './lldb/Link to Debuggers_General' -> '../Debuggers_General'
    2/4:    BROKEN: './Link to notes - Gabriel.odt' -> '/home/gabriel/GS/dev/notes - Gabriel.odt'
            FIXED : './Link to notes - Gabriel.odt' -> '/home/gabriel/GS/dev/RESEARCH/notes - Gabriel.odt'
            FINAL : './Link to notes - Gabriel.odt' -> 'notes - Gabriel.odt'
    3/4:    BROKEN: './books/Link to 104The Pragmatic Programmer, From Journeyman To Master - Andrew Hunt, David Thomas - Addison Wesley - 1999.pdf-1.desktop' -> '/home/gabriel/GS/dev/Design_Docs/104The Pragmatic Programmer, From Journeyman To Master - Andrew Hunt, David Thomas - Addison Wesley - 1999.pdf-1.desktop'
            FIXED : './books/Link to 104The Pragmatic Programmer, From Journeyman To Master - Andrew Hunt, David Thomas - Addison Wesley - 1999.pdf-1.desktop' -> '/home/gabriel/GS/dev/RESEARCH/Design_Docs/104The Pragmatic Programmer, From Journeyman To Master - Andrew Hunt, David Thomas - Addison Wesley - 1999.pdf-1.desktop'
            FINAL : './books/Link to 104The Pragmatic Programmer, From Journeyman To Master - Andrew Hunt, David Thomas - Addison Wesley - 1999.pdf-1.desktop' -> '../Design_Docs/104The Pragmatic Programmer, From Journeyman To Master - Andrew Hunt, David Thomas - Addison Wesley - 1999.pdf-1.desktop'
    4/4:    BROKEN: './books/TDD--James Grenning Test-Driven Dev for Embedded C/pragprog.com/Link to TDD_code' -> '/home/gabriel/GS/dev/books/TDD_code'
            FIXED : './books/TDD--James Grenning Test-Driven Dev for Embedded C/pragprog.com/Link to TDD_code' -> '/home/gabriel/GS/dev/RESEARCH/books/TDD_code'
            FINAL : './books/TDD--James Grenning Test-Driven Dev for Embedded C/pragprog.com/Link to TDD_code' -> '../../TDD_code'

************************************************************************
'--force' is on! New **relative** symlinks written!
************************************************************************

Run 'fix_broken_symlinks` "."' one more time to check if any symlinks are
still broken.

real    0m0.157s
user    0m0.101s
sys 0m0.086s

细节

我刚刚编写了一个工具,用来修复近 100 个损坏的符号链接。它被称为fix_broken_symlinks.sh,这是我的一部分eRCAGuy_dotfiles回购。

获取方法如下:

# download it and make it executable
wget https://raw.githubusercontent.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/master/useful_scripts/fix_broken_symlinks.sh
chmod +x fix_broken_symlinks

# help menu, with tons of info., & examples
./fix_broken_symlinks -h

一般用法和示例:

# General usage
fix_broken_symlinks path/to/dir find_regex replacement_str

# (Dry run) fix all broken symlinks in the current dir (.) by replacing their
# target paths with John's home dir instead of Gabriel's.
fix_broken_symlinks . '/home/gabriel/some/dir' 'home/john/some/dir'

# Pass `-f` to force it to actually apply the changes
fix_broken_symlinks . '/home/gabriel/some/dir' 'home/john/some/dir' -f

从帮助菜单:

'fix_broken_symlinks' version 0.1.0

USAGE
    fix_broken_symlinks [options] <dir> [<find_regex> <replacement_string>]

DESCRIPTION

    Find all broken symlinks in directory 'dir', then extract the target paths they point to, search
    those paths for 'find_regex', and replace those findings with 'replacement_string'. Finally,
    recreate the symlinks as relative symlinks with those replacements to the target paths in
    place.

    If the 'find_regex' and 'replacement_string' are not provided, it will simply find and print out
    the broken symlinks as they currently are.

    All runs are dry-runs unless you use '--force'.

OPTIONS
    -h, -?, --help
        Print help menu
    -v, --version
        Print version information.
    --run_tests
        Run unit tests.
    -d, --debug
        Turn on debug prints.
    -f, --force
        Actually do the symlink replacements. With*out* this option, all runs are dry runs.

EXAMPLE USAGES:

    fix_broken_symlinks -h
        Print help menu.
    fix_broken_symlinks --help
        Print help menu.
    fix_broken_symlinks .
        Recursively find all broken symlinks in the current directory (.).
    fix_broken_symlinks . '/home/gabriel/some/dir' 'home/john/some/dir'
        (Dry run) fix all broken symlinks in the current dir (.) by replacing their target paths
        with John's home dir instead of Gabriel's.
    fix_broken_symlinks . '/home/gabriel/some/dir' 'home/john/some/dir' -f
        (Real run) fix all broken symlinks in the current dir (.) by replacing their target paths
        with John's home dir instead of Gabriel's. **Relative** symlinks will be created in the end.

我使用的其他工具有:

  1. 使用以下命令手动修复一次性损坏的符号链接:

    注意:-n如果您要替换的符号链接是目录,则这是必需的。有关详细信息,请参阅以我的评论开头的讨论:如何“重新链接”大量损坏的符号链接?

    # NB: **All** of these options are important, and what I want. See 'man ln' 
    # for what each does.
    ln -svnri target_path symlink_path
    
  2. 将所有符号链接从绝对符号链接转换为相对符号链接:

    symlinks -rsvt .  # dry run
    symlinks -rsvc .  # the real replacement
    

    在 Ubuntu 中安装symlinks

    sudo add-apt-repository universe
    sudo apt update
    sudo apt install symlinks
    

    看:https://www.makeuseof.com/how-to-find-and-fix-broken-symlinks-in-linux/

更多我的笔记

看:

  1. fix_broken_symlinks -h
  2. 我在本文档中的注释如下:eRCaGuy_dotfiles/git 和 Linux cmd、帮助、提示和技巧 - Gabriel.txt。搜索它= Symlink Utilities: =

相关内容