次のパスは同じディスクの場所を指していますか?
/home/username
/app/home/username
ディレクトリを順番にそれぞれに変更し、pwd -P
の出力を確認します。 -P
フラグを使用すると、pwd
は、すべてのシンボリックリンクが解決された物理的な現在の作業ディレクトリを表示します。
_sd(){ set '' "$1" '' "${2?sd() requires two arguments!}"
while [ "$#" -gt 2 ]
do [ "${1:--L}" "${2:--L}" ${3:+"$4"} ] &&
[ "${1:--L}" ${3:+"-L"} "${3:-$4}" ] &&
[ "${2:-$3}" -ef "$4"/. ] && return || ${1:+"return"}
set "$@" "$2";shift 2;set ! "$@"
done 3>/dev/null 2>&"$((${#DBG}?2:3))"
}
_
sd()
最初に、両方の引数がシンボリックリンクであるかどうかを確認し、そうである場合は、次に、両方が同じiノードとデバイス番号のディレクトリにリンクされているかどうかを確認します。もしそうなら、sd()
return
s true
それができない場合は、両方がnotシンボリックリンクであるかどうか、また、両方が同じデバイス番号とiノード番号を持つディレクトリであるかどうかを確認します。それが失敗すると、falseが返されます。
そう...
_ln -s dir1 ln3; ln -s dir1 ln4; ln -s dir2 ln5
sd dir1 dir2; echo $?
1
sd dir1 ln3; echo $?
1
sd ln4 ln3; echo $?
0
sd ln4 ln5; echo $?
1
mount --bind dir1 dir2
sd dir1 dir2; echo $?
0
_
リンクをチェックせずに実行することが望ましい場合があります。たとえば、リンクのターゲットがディレクトリと同じであるかどうかを知りたい場合や、リンクであるかどうかをまったく気にしない場合などです。その場合、必要なのは1つの_[ fname1 -ef fname2 ]
_テストだけです。
ああ、これはすべての引数の検索権限を前提としていることにも言及する必要があると思います。呼び出し元のユーザーがテストの実行に必要な権限を持っていない場合は失敗します。
これらのフォルダを同期したり、相互にリンクしたりするために、どのメカニズム、仮想ファイルシステム、またはオーバーレイファイルシステムが存在するかを確認することはできません。単純なシンボリックリンクの場合、iノードは異なります。同じ場所であることを100%確実にするために、/home/username
にファイルを作成できます。
touch /home/username/.testfile
次に、両方の場所でそのファイルのiノード番号を比較します。
diff <(stat -c "%i" /home/username/.testfile) <(stat -c "%i" /app/home/username/.testfile)
それらが同じである場合、それは同じファイルであるため、同じ場所を指します。
それでも、100%確信は持てません。もちろん、両方のファイルシステムで次の空きiノードの番号が同じであるため、まったくの偶然によって同じiノード番号を持つことができます...
2つのファイルが同じであるかどうかを確認する基本的な方法は2つあります。 1つ目は、パスが同じかどうかをチェックすることです。これには誤検知はありませんが、誤検知はたくさんあります。フォールスネガティブの明らかなケースは、シンボリックリンクが含まれている場合です。シンボリックリンクを解決することで、そのケースを処理できます。変更する権限がある既存のディレクトリの場合、これはpwd -P
を使用して実行できます。
absolute_path1="$(cd -- "$path1" && pwd -P; echo .)" &&
absolute_path2="$(cd -- "$path2" && pwd -P; echo .)" &&
[ "$absolute_path1" = "$absolute_path2" ]
余分なecho .
は、ターゲットの1つに改行で終わるファイル名があるまれなケースを処理します。改行がコマンド置換の最後の文字である場合、それは削除されるため、スニペットは誤ってレポートします。そのfoo
はfoo
と同じです。
潜在的な偽陰性がまだあります。ほとんどのオペレーティングシステムとファイルシステムはディレクトリのハードリンクを禁止しているため、ディレクトリの場合、ハードリンクは問題になりません。発生する可能性があるのは、同じディレクトリが次のような異なる場所で利用可能になっていることです。
同じリモートファイルシステムを2つの異なる場所にマウントします。
mount server:/some/where /mnt1
mount server:/some/where /mnt2
compare /mnt1 /mnt2
A バインドマウント
これらの例では、ディレクトリが本当に同じであるかどうかは議論の余地があります。これは、エッジの場合の「同じファイル」の概念の限界を示しています。
2番目の基本的な方法は、カーネルによって提供されるIDをチェックすることです:デバイスとiノード。 stat
システムコール は、ファイルごとに2つの属性を報告します。
st_dev
)。これは、従来、ファイルが存在するファイルシステムを含むブロックデバイス(ディスクパーティション)のIDです。st_ino
)。これは、従来、同じファイルシステム内のファイルを識別する一意の番号です。通常、2つのファイルは、デバイス番号とiノード番号が同じである場合にのみ同一です。 Dash、ksh、bash、zsh、および少なくとも一部のBusyBoxビルド(プレーンなPOSIX shではない)には、次のことをテストするtest
ビルトインの-ef
演算子があります。
[ "$path1" -ef "$path2" ]
これにより、ハードリンクとシンボリックリンクが正しく処理されます(シンボリックリンクがたどられます。つまり、ファイルへのシンボリックリンクはターゲットファイルと同じと見なされます)。
シェル(またはtest
ユーティリティ)が-ef
をサポートしている場合、この方法は最も簡単に実行できます。ただし、すべてのファイルシステムが一意のiノード番号を報告するわけではないため、誤検知があることに注意してください。たとえば、ネットワークファイルシステムでは、リモートホストが選択したiノード番号に翻弄されます。多くのスタック可能なファイルシステムは、基になるiノードを報告します。これは、基になるディレクトリツリーが複数のファイルシステムにまたがる場合は一意ではありません。
別のアプローチは、観察可能な同等性をテストすることです:ディレクトリの1つを変更し、変更が他のディレクトリに反映されているかどうかを確認します。このアプローチには原則としてフォールスネガティブはありませんが、ディレクトリを変更する権限が必要であり、これらのディレクトリを使用しているシステムの他の部分を混乱させる可能性があります。変更が反映されていることを確認すると、ディレクトリを非常に迅速に同期しているデーモンがあることを示している可能性があるため、誤検知が発生する可能性があります。
/home/username
と/app/home/username
がディレクトリであるとすると、iノード番号をチェックしてそれらが同じパスであるかどうかを確認することはできません。これは、ディレクトリをハードリンクすることができず、ソフトリンクが異なるiノードを持っているためです。
ファイルをcd /home/username
、touch
して、他の/app/home/username
に表示されるかどうかを確認できます。おそらくもっと良い方法があります。誰かがもっと良い答えを出せるなら、先に進んでください。
marco の内容を拡張すると:GNU/Linuxではls -li /home/username /app/home/username
はすでに良いヒントを提供します。両方のiノードが等しい可能性がある場合、それらは同じ場所を指しています。 mount
で再確認してください。 /home/username
内のファイルをtouch
- ingしてトリプルチェックし、同じiノードで/app/home/username
およびに表示されるかどうかを確認します。そうすれば、それが同じディレクトリであるとかなり確信できます。
Linux Mintマシン、3.11.0-12で行われたテスト-汎用カーネル:
# ls -ldi /var
2 drwxr-xr-x 13 root root 4096 jan 13 2014 /var
# mkdir /mnt/var
# ls -ldi /mnt/var
266483 drwxr-xr-x 2 root root 4096 jun 2 10:43 /mnt/var
# mount --bind /var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 2 root root 4096 jun 2 10:43 /mnt/var
# umount /mnt/var
# mount /dev/mapper/mint--vg-var /mnt/var
# ls -ldi /mnt/var
2 drwxr-xr-x 13 root root 4096 jan 13 2014 /mnt/var
結論:私はthinkyoucanで、iノードをチェックして2つのディレクトリがマウントポイントであれば同一であることを確認します。シンボリックリンクの場合、もちろん上記は当てはまりません。しかし、それは明らかです。
# rmdir /mnt/var
# ln -s /var /mnt/
# ls -ldi /mnt/var
266483 lrwxrwxrwx 1 root root 4 jun 2 10:51 /mnt/var -> /var