ファイルをバージョン管理下に置くために、ホーム ディレクトリから設定ディレクトリへのシンボリック リンクを再帰的に作成するスクリプトがあります。親ディレクトリ経由ですでにシンボリック リンクされているファイルをスキップしたいと思います。つまり、次のファイル/ディレクトリがあるとします。
~/foo/ -> ~/settings/foo/
~/settings/foo/
~/settings/foo/bar
~/foo/bar と ~/settings/foo/bar が同じファイルであることを確認するにはどうすればよいですか?
編集: ああ、さらに数分検索してみると、答え:readlink -f $path
答え1
2 つのファイルに同じデバイス ID と inode がある場合、それらは同じファイルです。stat
コマンドライン ツールを使用すると、これを簡単に見つけることができ、このソリューションは POSIX シェルに準拠しています。
if [ "$(stat -L -c %d:%i FILE1)" = "$(stat -L -c %d:%i FILE2)" ]; then
echo "FILE1 and FILE2 refer to a single file, with one inode, on one device."
else
echo "no match"
fi
-L
それぞれのフラグは、シンボリックstat
リンクされたファイルとハードリンクされたファイルの両方で機能することを意味します。
答え2
多くのシェルには組み込み-ef
の演算子test
(またはその同義語[
)があり、2つのパスが同じ既存ファイル(シンボリック リンクをたどる)。これには、bash、dash、pdksh、ksh88、ksh93、zsh が含まれますが、POSIX sh は含まれません。bash、ksh、zsh では、条件構文-ef
で を使用することもできます[[ … ]]
。
if ! [ "$1" -ef "$2" ]; then # $1 and $2 are different files
答え3
ソフトリンク ( で作成ln -s
) の場合は を使用できますrealpath
。ただし、これはハードリンクでは機能しません。