Shell-编辑软链接的脚本 - 绝对到相对
Shell-Script for editing softlink - absolute to relative
我需要编辑一些损坏的软链接,因为它们是绝对的。我想把它们送给一些亲戚。为此,我需要计算它们指向的路径的起始目录深度。然后我需要用 ../ 替换这些计数的目录,因为我只需要起床,直到找到匹配的目录。
我已经找到失效链接的行:
find -type l | while read f; do if [ ! -e "$f" ]; then ls -l "$f"; fi; done
这行得通,所以我可以找到损坏的,但我不知道如何继续。
编辑:
我发现以下解决方案有效:
depthRoot=2 # Depth of root-directory
find -type l |
while read f
do
if [ ! -e "$f" ] # broken link found (put in variable f)
then
echo "Link found: $f" # output of broken link
previous="$(readlink "$f")" # target of broken link in variable previous
echo "points to: $previous" # output of target
y=$"${f//[^\/]}" # generating string of f with all the slashs
depthFrom=${#y} # count length of y an put value in depthFrom
depthFrom=`expr $depthFrom - 1`
echo "Depth place = $depthFrom" # output of depth of place of broken link
y=$"${previous//[^\/]}" # generating string of previous with all the slashs
depthTarget=${#y} # count length of y an put value in depthTarget
depthTarget=`expr $depthTarget - $depthRoot - 1` # subtraction of depth of root-directory
echo "Depth target = $depthTarget" # output of depth of target of link
depthRoot=`expr $depthRoot + 1` # root-directory-depth +1 (1 Directory - 2 Slashs)
depth=`expr $depthFrom - $depthTarget` # calculate difference in depth
echo "difference of depth = $depth" # output of differrence of depth
while [ $depthRoot -gt 0 ] # while depthRoot > 0
do
depthRoot=`expr $depthRoot - 1` # decrement depthRoot by 1
previous=${previous#*/} # erease everything of previous until first Slash leftside
done
f=${f:2} # subtract ./ of f
tofind="$(echo "$previous"| sed -e 's/[\/&]/\&/g')" # escape subdirectories of previous
tofind=${tofind%\*} # erease everything on the right side until first backslash
newlink="$(echo "$f"| sed "s/$tofind//g")" # erease existing side on the left
newlink=${newlink:1}
while [ $depth -gt 0 ] # while depth > 1
do
newlinkaddition=$newlinkaddition"../" # generating ../ for relative links
newlink=${newlink#*/} # remove old directories which will be replaced by ../
depth=`expr $depth - 1` # decrement depth
done
newlink=$newlinkaddition$newlink # generating target of new link
rm $f # erease old link
ln -s "$newlink" "$" # generating new link
echo "new link generated: $newlink -> $f" # output of successfull generation of new link
fi
done
问题是您需要知道所有损坏的 link 都有一个共同的根。
例如在我的试用中,你的代码给了我这个输出
lrwxrwxrwx 1 user group 10 Aug 10 17:31 ./a/c -> /tmp/old/c
在这种情况下,共同根是 /tmp/old
因此必须将其删除并替换为相对 link 到应该是当前目录的新位置
oldroot=/tmp/old/ # needs / at the end!
find -type l |
while read f
do
if [ ! -e "$f" ] # dead link found
then
f="${f#./}" # remove ^./ from find result
echo "found link $f"
previous="$(readlink "$f")" # get old destination
echo "pointing to $previous"
previous="${previous#$oldroot}" # remove oldroot
newlink="$(echo "$f"|awk 'BEGIN{FS=OFS="/"}{for(i=1;i<NF;i++){printf "../"}}END{print "."}')"
newlink="$(echo "$newlink/$previous"|sed 's,/\./,/,g')"
echo "creating link $f -> $newlink"
rm $f
ln -s "$newlink" "$f"
fi
done
此解决方案使用 awk 和 sed。也许在 bash 中也可以这样做,但在这种情况下我更愿意使用 awk & sed。
我需要编辑一些损坏的软链接,因为它们是绝对的。我想把它们送给一些亲戚。为此,我需要计算它们指向的路径的起始目录深度。然后我需要用 ../ 替换这些计数的目录,因为我只需要起床,直到找到匹配的目录。
我已经找到失效链接的行:
find -type l | while read f; do if [ ! -e "$f" ]; then ls -l "$f"; fi; done
这行得通,所以我可以找到损坏的,但我不知道如何继续。
编辑: 我发现以下解决方案有效:
depthRoot=2 # Depth of root-directory
find -type l |
while read f
do
if [ ! -e "$f" ] # broken link found (put in variable f)
then
echo "Link found: $f" # output of broken link
previous="$(readlink "$f")" # target of broken link in variable previous
echo "points to: $previous" # output of target
y=$"${f//[^\/]}" # generating string of f with all the slashs
depthFrom=${#y} # count length of y an put value in depthFrom
depthFrom=`expr $depthFrom - 1`
echo "Depth place = $depthFrom" # output of depth of place of broken link
y=$"${previous//[^\/]}" # generating string of previous with all the slashs
depthTarget=${#y} # count length of y an put value in depthTarget
depthTarget=`expr $depthTarget - $depthRoot - 1` # subtraction of depth of root-directory
echo "Depth target = $depthTarget" # output of depth of target of link
depthRoot=`expr $depthRoot + 1` # root-directory-depth +1 (1 Directory - 2 Slashs)
depth=`expr $depthFrom - $depthTarget` # calculate difference in depth
echo "difference of depth = $depth" # output of differrence of depth
while [ $depthRoot -gt 0 ] # while depthRoot > 0
do
depthRoot=`expr $depthRoot - 1` # decrement depthRoot by 1
previous=${previous#*/} # erease everything of previous until first Slash leftside
done
f=${f:2} # subtract ./ of f
tofind="$(echo "$previous"| sed -e 's/[\/&]/\&/g')" # escape subdirectories of previous
tofind=${tofind%\*} # erease everything on the right side until first backslash
newlink="$(echo "$f"| sed "s/$tofind//g")" # erease existing side on the left
newlink=${newlink:1}
while [ $depth -gt 0 ] # while depth > 1
do
newlinkaddition=$newlinkaddition"../" # generating ../ for relative links
newlink=${newlink#*/} # remove old directories which will be replaced by ../
depth=`expr $depth - 1` # decrement depth
done
newlink=$newlinkaddition$newlink # generating target of new link
rm $f # erease old link
ln -s "$newlink" "$" # generating new link
echo "new link generated: $newlink -> $f" # output of successfull generation of new link
fi
done
问题是您需要知道所有损坏的 link 都有一个共同的根。
例如在我的试用中,你的代码给了我这个输出
lrwxrwxrwx 1 user group 10 Aug 10 17:31 ./a/c -> /tmp/old/c
在这种情况下,共同根是 /tmp/old
因此必须将其删除并替换为相对 link 到应该是当前目录的新位置
oldroot=/tmp/old/ # needs / at the end!
find -type l |
while read f
do
if [ ! -e "$f" ] # dead link found
then
f="${f#./}" # remove ^./ from find result
echo "found link $f"
previous="$(readlink "$f")" # get old destination
echo "pointing to $previous"
previous="${previous#$oldroot}" # remove oldroot
newlink="$(echo "$f"|awk 'BEGIN{FS=OFS="/"}{for(i=1;i<NF;i++){printf "../"}}END{print "."}')"
newlink="$(echo "$newlink/$previous"|sed 's,/\./,/,g')"
echo "creating link $f -> $newlink"
rm $f
ln -s "$newlink" "$f"
fi
done
此解决方案使用 awk 和 sed。也许在 bash 中也可以这样做,但在这种情况下我更愿意使用 awk & sed。