os.stat()
を壊れたsymlink
に電話すると、pythonはOSError
例外をスローします。これはそれを見つけるのに役立ちます。しかし、os.stat()
が同様の例外をスローする可能性がある他の理由がいくつかあります。 LinuxでPythonを使って壊れたsymlinks
を検出するより正確な方法はありますか?Pythonで壊れているシンボリックリンクを見つけよう
答えて
共通Pythonのことわざは、それがより許しを依頼することが容易であるということです許可。私は実生活でこの声明のファンではありませんが、それは多くの場合に当てはまります。通常は、コード内の2つの呼び出しの間にファイルに何が起こるかを決して知らないので、同じファイルに対して2つのシステム呼び出しを連結するコードを避けたいとします。何かがあなたの場合は、テスト後にそれを削除した場合、失敗する例外を発生させ、残りを停止することがあります
if os.path.exists(path):
os.unlink(path)
2回目の呼び出し(os.unlink):
典型的な間違いがような何かを書くことですあなたの関数の実行から。(これは実際には起こらないと思うかもしれませんが、先週のコードベースのような別のバグを釣ったばかりです - それはいくつかのプログラマーが頭を掻き、「Heisenbug」を過去数ヶ月)
だから、あなたの特定のケースでは、私はおそらくだろう:
try:
os.stat(path)
except OSError, e:
if e.errno == errno.ENOENT:
print 'path %s does not exist or is a broken symlink' % path
else:
raise e
をここに迷惑がstatにだけ存在しないシンボリックリンクで同じエラーコードと壊れを返すということですシンボリックリンク。
だから、私はあなたがアトミックを破るよりも選択肢がないと思い、そして
if not os.path.exists(os.readlink(path)):
print 'path %s is a broken symlink' % path
pythonのないハードリンクのテストについて言及できますか?/bin/testには、FILE1 -ef FILE2条件があります。これは、ファイルがiノードを共有する場合にtrueになります。
したがって、find . -type f -exec test \{} -ef /path/to/file \; -print
のようなものは、特定のファイルへのハードリンクテストに使用できます。 man test
を読みに私をもたらし、そのファイルがシンボリックリンクの場合は、1つのファイルの両方の仕事とは、ターゲットが欠落しているかどうかを教えてくれないことが、trueを返した-L
と-h
の言及
。通常のファイルへのシンボリックリンクの場合には、それが標的にすることができるのかどうかのためのテストとして働く
私は、ファイルを開くことができる場合head -0 FILE1
は0
の終了コードを返すことがわかりましたと1
それができない場合は、読まれる。
私はpythonの人ではありませんが、os.readlink()のように見えますか?私がperlで使うロジックは、readlink()を使ってターゲットを探し、stat()を使ってターゲットが存在するかどうかを調べることです。
編集:私はいくつかのperlを試してreadlinkをデモしました。私はperlのSTATを信じ、READLINKとPythonのはos.stat()とos.readlink()システムコールの両方のラッパーなので、これは合理的な翻訳すべきであるだけでなく、概念実証コード:
wembley 0 /home/jj33/swap > cat p
my $f = shift;
while (my $l = readlink($f)) {
print "$f -> $l\n";
$f = $l;
}
if (!-e $f) {
print "$f doesn't exist\n";
}
wembley 0 /home/jj33/swap > ls -l | grep ^l
lrwxrwxrwx 1 jj33 users 17 Aug 21 14:30 link -> non-existant-file
lrwxrwxrwx 1 root users 31 Oct 10 2007 mm -> ../systems/mm/20071009-rewrite//
lrwxrwxrwx 1 jj33 users 2 Aug 21 14:34 mmm -> mm/
wembley 0 /home/jj33/swap > perl p mm
mm -> ../systems/mm/20071009-rewrite/
wembley 0 /home/jj33/swap > perl p mmm
mmm -> mm
mm -> ../systems/mm/20071009-rewrite/
wembley 0 /home/jj33/swap > perl p link
link -> non-existant-file
non-existant-file doesn't exist
wembley 0 /home/jj33/swap >
os.lstat()が役立つかもしれません。 lstat()が成功し、stat()が失敗すると、リンクが壊れている可能性があります。
あなたがへのシンボリックリンクのポイントは、それが使用して有効なファイルかどうかを決定しようとしているものを手に入れるのrealpath()を使用してみてはファイルです。
(あなたがそれで遊んで、あなたが得るかを確認する必要がありますので、私は、現時点ではそれを試してみることができないんだけど)
これはアトミックではありませんが、それが動作するような何かを行います。 RTFM (幻想マニュアルを読む)によって、実際
os.path.islink(filename) and not os.path.exists(filename)
パスは、既存のパスを参照している場合、我々は真
os.path.exists(パス)
リターンを参照してください。壊れたシンボリックリンクに対してFalseを返します。
また、言う:許可がパスが物理的に存在する場合でも、要求されたファイルに()はos.statを実行するために付与されていない場合、一部のプラットフォームで
は、この関数はFalseを返す場合があります。
権限が不安な場合は、他の句を追加する必要があります。
+1を指しています。 – esmit
私は同じような問題がありました:親リンクで発生した場合でも、壊れたシンボリックリンクをどのように捕まえることができますか?私はまた、(かなり多数のファイルを扱うアプリケーションで)すべてをログに記録したいと思っていましたが、あまりにも多くの繰り返しは必要ありませんでした。
ユニットテストを含めて私が思いついたのはこれです。
fileutil.py:
import os
from functools import lru_cache
import logging
logger = logging.getLogger(__name__)
@lru_cache(maxsize=2000)
def check_broken_link(filename):
"""
Check for broken symlinks, either at the file level, or in the
hierarchy of parent dirs.
If it finds a broken link, an ERROR message is logged.
The function is cached, so that the same error messages are not repeated.
Args:
filename: file to check
Returns:
True if the file (or one of its parents) is a broken symlink.
False otherwise (i.e. either it exists or not, but no element
on its path is a broken link).
"""
if os.path.isfile(filename) or os.path.isdir(filename):
return False
if os.path.islink(filename):
# there is a symlink, but it is dead (pointing nowhere)
link = os.readlink(filename)
logger.error('broken symlink: {} -> {}'.format(filename, link))
return True
# ok, we have either:
# 1. a filename that simply doesn't exist (but the containing dir
does exist), or
# 2. a broken link in some parent dir
parent = os.path.dirname(filename)
if parent == filename:
# reached root
return False
return check_broken_link(parent)
ユニットテスト:シンボリックリンクがディレクトリのファイルをmissuses場合
import logging
import shutil
import tempfile
import os
import unittest
from ..util import fileutil
class TestFile(unittest.TestCase):
def _mkdir(self, path, create=True):
d = os.path.join(self.test_dir, path)
if create:
os.makedirs(d, exist_ok=True)
return d
def _mkfile(self, path, create=True):
f = os.path.join(self.test_dir, path)
if create:
d = os.path.dirname(f)
os.makedirs(d, exist_ok=True)
with open(f, mode='w') as fp:
fp.write('hello')
return f
def _mklink(self, target, path):
f = os.path.join(self.test_dir, path)
d = os.path.dirname(f)
os.makedirs(d, exist_ok=True)
os.symlink(target, f)
return f
def setUp(self):
# reset the lru_cache of check_broken_link
fileutil.check_broken_link.cache_clear()
# create a temporary directory for our tests
self.test_dir = tempfile.mkdtemp()
# create a small tree of dirs, files, and symlinks
self._mkfile('a/b/c/foo.txt')
self._mklink('b', 'a/x')
self._mklink('b/c/foo.txt', 'a/f')
self._mklink('../..', 'a/b/c/y')
self._mklink('not_exist.txt', 'a/b/c/bad_link.txt')
bad_path = self._mkfile('a/XXX/c/foo.txt', create=False)
self._mklink(bad_path, 'a/b/c/bad_path.txt')
self._mklink('not_a_dir', 'a/bad_dir')
def tearDown(self):
# Remove the directory after the test
shutil.rmtree(self.test_dir)
def catch_check_broken_link(self, expected_errors, expected_result, path):
filename = self._mkfile(path, create=False)
with self.assertLogs(level='ERROR') as cm:
result = fileutil.check_broken_link(filename)
logging.critical('nothing') # trick: emit one extra message, so the with assertLogs block doesn't fail
error_logs = [r for r in cm.records if r.levelname is 'ERROR']
actual_errors = len(error_logs)
self.assertEqual(expected_result, result, msg=path)
self.assertEqual(expected_errors, actual_errors, msg=path)
def test_check_broken_link_exists(self):
self.catch_check_broken_link(0, False, 'a/b/c/foo.txt')
self.catch_check_broken_link(0, False, 'a/x/c/foo.txt')
self.catch_check_broken_link(0, False, 'a/f')
self.catch_check_broken_link(0, False, 'a/b/c/y/b/c/y/b/c/foo.txt')
def test_check_broken_link_notfound(self):
self.catch_check_broken_link(0, False, 'a/b/c/not_found.txt')
def test_check_broken_link_badlink(self):
self.catch_check_broken_link(1, True, 'a/b/c/bad_link.txt')
self.catch_check_broken_link(0, True, 'a/b/c/bad_link.txt')
def test_check_broken_link_badpath(self):
self.catch_check_broken_link(1, True, 'a/b/c/bad_path.txt')
self.catch_check_broken_link(0, True, 'a/b/c/bad_path.txt')
def test_check_broken_link_badparent(self):
self.catch_check_broken_link(1, True, 'a/bad_dir/c/foo.txt')
self.catch_check_broken_link(0, True, 'a/bad_dir/c/foo.txt')
# bad link, but shouldn't log a new error:
self.catch_check_broken_link(0, True, 'a/bad_dir/c')
# bad link, but shouldn't log a new error:
self.catch_check_broken_link(0, True, 'a/bad_dir')
if __name__ == '__main__':
unittest.main()
- 1. ディレクトリ内のシンボリックリンクを見つける
- 2. VB.NETを使用してシンボリックリンクのターゲットを見つけるにはどうすればよいですか?
- 3. シンボリックリンクがどのディレクトリに含まれているかわからないときにシンボリックリンクを見つける?
- 4. PHPで実行されているスクリプトを見つけよう
- 5. Perlが壊れているようです: "=:見つからない"と "パッケージ:見つからない"
- 6. 別のシンボリックリンクを指し示すアイコンのシンボリックリンクを見つける方法
- 7. H2O.apply python関数が壊れているようです
- 8. DotNetNukeで壊れた内部リンクを見つける
- 9. メモ帳で壊れた行を見つける++
- 10. ジークの壊れたフロントの問題、壊れたファイルを見つける方法?
- 11. 繰り返し実行を見つけて壊れます
- 12. Python配列で指定された数に近い値を見つけよう
- 13. 壊れたリンクのないすべてのファイルを見つける
- 14. Python - すべての和を見つけよう
- 15. JAVAシンボリックリンクが指し示すターゲットファイルパスを見つける方法は?
- 16. Pythonでcsvファイルの空の列を見つけようとしています
- 17. Pythonリスト(Python 3.6)で数値に最も近い値を見つけよう
- 18. SQL Serverで欠落しているルートを見つけよう
- 19. Goで壊れたシンボリックリンクを検出するにはどうすればよいですか?
- 20. ウェブサイト上の壊れたリンクを見つける方法
- 21. リスト内のサブリストの位置をPythonで見つけよう
- 22. Pythonリストのタプルで一意の要素を見つけよう
- 23. リスト内のタプル付き要素をPythonで見つけよう
- 24. エラーPythonを見つける
- 25. NEAT-PythonがVisualize.pyを見つけられていない
- 26. のperlからバッククォートで見つける呼び出す - 見つける:書き込みエラー:壊れたパイプ
- 27. ビジュアルスタジオ2012でWindowsデザイナーを見ているコントロールを見つけるにはどうすればよいですか?
- 28. Pythonを使用してISOファイルのMD5ハッシュを見つけるにはどうすればよいですか?
- 29. Pythonを使用してWindowsの共通アプリケーションデータフォルダを見つけるにはどうすればよいですか?
- 30. Pythonを使用して特定のファイルを見つけるにはどうすればよいですか?
READLINKもerrnoに== ENOTDIRを設定することができます。 –
リンク 'path'にターゲットへの相対パスが指定されている場合、os.readlink(path)は実際のパスを取得しない可能性があります。たとえば、pathが '../target'にリンクされている場合、リンクが存在するパスにないスクリプトを実行すると、os.path.exists(os.readlink(path))はパスにfalseが返されますその上位ディレクトリには 'target'という名前のファイルやフォルダはありません。これを回避する安全な方法は、os.path.exists(os.path.realpath(path))を使用することです。 – AplusG
これでさえ十分ではありません。 realpathは、現在実行中のスクリプトの現在の実行ディレクトリに対するシンボリックリンクのパスを解釈しますが、シンボリックリンクはシンボリックリンクがあるフォルダに対するOSによって解釈されます。あなたがする必要があるのは、次のようなことです: link_target = os.readlink(パス) dir = os.path.dirname(パス) os.pathでない場合は、次のようにします。あなたがこの悪いシンボリックリンクで好きなことをしてください –