Заменить символическую ссылку на цель

Как вы можете заменить все символические ссылки в каталоге (и дочерние элементы) их целями в Mac OS X? Если цель недоступна, я бы предпочел оставить мягкую ссылку в покое.

3 ответа

Решение

Если вы используете псевдонимы Mac OSX, то find . -type l ничего не придумаешь

Вы можете использовать следующий скрипт [Node.js] для перемещения / копирования целей ваших символических ссылок в другой каталог:

fs = require('fs')
path = require('path')

sourcePath = 'the path that contains the symlinks'
targetPath = 'the path that contains the targets'
outPath = 'the path that you want the targets to be moved to'

fs.readdir sourcePath, (err,sourceFiles) ->
    throw err if err

    fs.readdir targetPath, (err,targetFiles) ->
        throw err if err

        for sourceFile in sourceFiles
            if sourceFile in targetFiles
                targetFilePath = path.join(targetPath,sourceFile)
                outFilePath = path.join(outPath,sourceFile)

                console.log """
                    Moving: #{targetFilePath}
                        to: #{outFilePath}
                    """
                fs.renameSync(targetFilePath,outFilePath)

                # if you don't want them oved, you can use fs.cpSync instead

Вот версии ответа Chmeee, который использует readlink и будет работать правильно, если в любом имени файла есть пробелы:

Новое имя файла соответствует старому имени ссылки:

find . -type l | while read -r link
do 
    target=$(readlink "$link")
    if [ -e "$target" ]
    then
        rm "$link" && cp "$target" "$link" || echo "ERROR: Unable to change $link to $target"
    else
        # remove the ": # " from the following line to enable the error message
        : # echo "ERROR: Broken symlink"
    fi
done

Новое имя файла соответствует имени цели:

find . -type l | while read -r link
do
    target=$(readlink "$link")
    # using readlink here along with the extra test in the if prevents
    # attempts to copy files on top of themselves
    new=$(readlink -f "$(dirname "$link")/$(basename "$target")")
    if [ -e "$target" -a "$new" != "$target" ]
    then
        rm "$link" && cp "$target" "$new" || echo "ERROR: Unable to change $link to $new"
    else
        # remove the ": # " from the following line to enable the error message
        : # echo "ERROR: Broken symlink or destination file already exists"
    fi
done

Вы не сказали, какие имена должны иметь файлы после замены.

Этот скрипт считает, что замененные ссылки должны иметь те же имена, что и ссылки.

for link in `find . -type l`
do 
  target=`\ls -ld $link | sed 's/^.* -> \(.*\)/\1/'`
  test -e "$target" && (rm "$link"; cp "$target" "$link")
done

Если вы хотите, чтобы файлы имели то же имя, что и цель, это должно быть сделано.

for link in `find . -type l`
do
  target=`\ls -ld $link | sed 's/^.* -> \(.*\)/\1/'`
  test -e "$target" && (rm $link; cp "$target" `dirname "$link"`/`basename "$target"`)
done
Другие вопросы по тегам