我有以下目录结构
/symdir
sym1 -> ../dir1
sym2 -> ../dir2
hello.txt
然后
/dir1
some
files
here
/dir2
more
files
我想将symdir(sym1,sym2)中的符号链接替换为原始符号。即。
some_awesome_bash_func symdir symdir_output
会创建
/symdir_output
/dir1
some
files
here
/dir2
more
files
hello.txt
我将如何做到这一点?
答案 0 :(得分:64)
我个人的伎俩:
sed -i '' **/*
请注意,我使用的是使用bash globstar选项的**
,您可能需要事先启用它:
shopt -s globstar
答案 1 :(得分:21)
您可以使用rsync轻松完成此操作:
rsync symdir/ symdir_output/ -a --copy-links -v
( - 一种方法基本上保留了关于文件的每个细节, - copy-links覆盖-a将符号链接转换为真实文件/目录,-v用于详细)
编辑:
很抱歉,我的解决方案并不能满足您的要求。它将保留符号链接的名称,而不是使用目标名称。 symdir_output将有sym1和sym2而不是dir1和dir2(虽然sym1和sym2将是dir1和dir2的真实副本)。希望它仍然适合你。
答案 2 :(得分:12)
相关答案,此解决方案将文件保留在原始位置并创建副本以代替符号链接
#/bin/bash
for f in $(find . -maxdepth 1 -type l)
do
cp --remove-destination $(readlink -e $f) $f
done
答案 3 :(得分:10)
可能不是最好的方式,但它有效:
#!/usr/bin/bash
for link in $(find /symdir -type l)
do
loc="$(dirname "$link")"
dir="$(readlink "$link")"
mv "$dir" "$loc"
rm "$link"
done
答案 4 :(得分:6)
tl; dr:更一般,更可靠的答案:
find -type l -exec sh -c 'PREV=$(realpath -- "$1") && rm -- "$1" && cp -ar -- "$PREV" "$1"' resolver {} \;
“rsync-to-other-destination”方法非常优越,通常可以带来更好的设计。
@PinkFloyd的答案与不寻常的文件名,“埋藏”符号链接或符号链接目录不太一致。我来到这里是因为我想解析目录符号链接,所以我希望其他人也可以出于这个原因找到这个问题。另外,我的cp
版本(GNU coreutils 8.25)无法正确处理@ {Pinkis = @FloFloyd使用目录的答案--remove-destination
。所以这个答案使用了手册rm
。
另请注意:
-rf
。这是因为符号链接不是目录,不应该需要-r
。除非你有限制权限的符号链接(为什么你会想要?),你也不需要-f
。realpath
在这种情况下非常好,因为它允许我们在当前上下文中找出当前系统中的实际位置,而其他任何事情都不重要。此路径不会写入磁盘,因此这不是错误。resolver
字符串适用于sh
。请参阅man sh
。--version
或类似符号,则必须在任何地方使用双破折号。find
的预订保证(“父目录在其内容之前的某处列出”),这将首先替换父目录,然后替换符号链接目录中的任何符号链接。所以它可以与“堆叠”符号链接完美搭配。答案 5 :(得分:1)
我是这样做的:
ls -la | awk '/-\>/{system("rm "$10); system("cp "$12" .")}'
工作原理:
ls -la
输出如下内容:
lrwxr-xr-x 1 username groupname 44 10 Oct 12:17 Queue.swift -> ../../../Platform/DataStructures/Queue.swift
第10列是Queue.swift
,它是本地文件的名称
第12列是../../../Platform/DataStructures/Queue.swift
,它是链接目标的名称
awk
命令的第一部分是'/-\>/'
,表示“使用正则表达式匹配包含->
的行
awk命令的下一部分是对system
首先system("rm "$10)
扩展为system("rm Queue.swift")
这将导致原始文件(符号链接)被删除
第二个是system("cp "$12" .")
,它扩展为system("cp ../../../Platform/DataStructures/Queue.swift .")
总而言之,每个文件(这是一个符号链接)会发生什么,首先我们删除符号链接,然后我们将目标文件复制到它的位置。
虽然它不是原始问题的一部分,但我将它与git结合使用。如果您碰巧也是这样做的,那么之后您可以运行git status .
,您应该看到一堆类型更改(没有别的),如下所示:
typechange: Queue.swift
答案 6 :(得分:1)
扩展 Julien 的建议。此命令递归地将当前目录中的所有符号链接替换为其目标。
find . -type l -exec sed -i '' {} \;
find .
:在当前目录中递归搜索-type l
:仅查找符号链接-exec sed -i '' {} \;
:为每个符号链接运行 sed -i '' PATH
。请参阅 Julien 的回答,了解我们为何在此处使用 sed
。答案 7 :(得分:0)
这是一个基于@Daniel Haley的更通用的解决方案
它还会保留符号链接以供参考,并要求用户选择要编辑的目录。
ls
read -p 'Which directory do you want to update?: ' linkdir
pushd $linkdir
for linkname in $(find ./ -type l)
do
orig=$(readlink $linkname)
mv $linkname ${linkname}.linkbak
cp $orig $linkname
done
popd