絶対シンボリックリンクターゲットを出力する非再帰readlink -f
/代替方法はありますか?realpath
より多くのPOSIX互換ソリューションも歓迎します。
シェルスクリプトには次の関数ブロックがあります。
set FILES
# addFile adds a file to the FILES list. If file is a symlink,
# it will also find and add the destination.
addFile() {
file="$1"
# Check if file is already included in list
echo "$FILES" | grep -q "$file" && return
FILES="$FILES $file"
if [ -L $file ]; then
addFile $(realpath $file)
#addFile $(readlink $file)
fi
}
私はファイルシステムからバイナリとライブラリファイルを収集するスクリプトでこの関数を使用しています。ただし、このコードには問題があると予想されます。
- 最初の試みは成功しましたが、
readlink
相対的なシンボリックリンク検証パスを返したため、そのパス$file
で実行されたすべての操作は失敗しました。 (現在コメントされていますが、まだコードにあります)(以下の小さな編集を参照) - その後、
realpath
提案どおりに使用しましたman readlink
。これでほとんど使用する準備が整いました。
今私がしたいことはうまくいっています。しかし、最終的な結果は、initramfsのすべてのバイナリ、ライブラリ、およびシンボリックリンクをコピーすることです。再帰シンボリックリンクがある場合は、中間シンボリックリンクではなく、最上位レベルと宛先のみが含まれます。したがって、シンボリックリンクが切断されました。
私ヴァイオリンこの問題を示すために。link-to-link1
ポイントlink1
、ポイントですfile1
。最終結果link1
が失われ、link-to-link1
破損しています。
質問を明確に修正してください。
次のシンボリックリンクセットで上記の関数を実行するとき:
# Contents of ~/test/src
file0
file1
link0 -> file0
link0.1 -> file0
link1 -> file1
link-to-link1 -> link1
そして:
copy="link-to-link1 link0 link0.1"
for sf in $copy; do
addFile ~/test/src/$sf
done;
cp -av $FILES ~/test/dst
$copy
3つのリンクと2つのファイルのみがコピーされていることを確認できます。しかし、中間リンクlink1
がありlink-to-link1
ません。
link1
私もその台本を探したいです。このスクリプトが実行される環境では、ファイルとシンボリックリンクの場所が絶対的でなければならないことに注意してください。
マイナーな編集
次へ追加別のヴァイオリン相対パスの失敗を示すためにreadlink
.を使用すると、シンボリックリンクのみがコピーされ、宛先がありません。
答え1
私が正しく理解したら、与えられた例ではlink1
ファイルが欲しいでしょうlink-to-link1
。find
GNUと-printf
以下を使用して取得できます%l
。
$ find . -type l -printf '%p -> %l\n'
./link0.1 -> file0
./link1 -> file1
./link0 -> file0
./link-to-link1 -> link1
link1
出力に絶対パスが必要なので、/path/to/link-to-link1
/を含めて実行するディレクトリにすることができますcd
。link-to-link1
readlink
realpath
(
cd "$(dirname "$file")"
realpath -s "$(readlink "$file")"
)
realpath -s
シンボリックリンクは確認されませんが、絶対パスは印刷されます。
たとえば、
~ file=/tmp/foo/link-to-link1
~ (cd "$(dirname "$file")"; realpath -s "$(readlink "$file")")
/tmp/foo/link1
これは絶対パスを持つリンクにも当てはまります。
~ file=/tmp/foo/link2
~ ln -sfv /tmp/foo/link1 "$file"
'/tmp/foo/link2' -> '/tmp/foo/link1'
~ (cd "$(dirname "$file")"; realpath -s "$(readlink "$file")")
/tmp/foo/link1