51

内の dir1 (ファイルまたはディレクトリ) のすべての項目に対してシンボリック リンクを作成する必要がありますdir2dir2既に存在し、シンボリック リンクではありません。Bash では、次の方法で簡単に実現できます。

ln -s /home/guest/dir1/* /home/guest/dir2/

しかし、pythonを使用os.symlinkするとエラーが発生します:

>>> os.symlink('/home/guest/dir1/*', '/home/guest/dir2/')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 17] File exist

subprocessコマンドを使用して実行できることを知っていますln。私はその解決策を望んでいません。

os.walkまたはを使用した回避策が可能であることも認識してglob.globいますが、 を使用してこれを行うことができるかどうかを知りたいですos.symlink

4

3 に答える 3

68

os.symlink単一のシンボリックリンクを作成します。

ln -s複数のシンボリックリンクを作成します (最後の引数がディレクトリで、複数のソースがある場合)。同等の Python は次のようなものです。

dst = args[-1]
for src in args[:-1]:
    os.symlink(src, os.path.join(dst, os.path.dirname(src)))

それで、あなたがそうするとき、それはどのように機能しますln -s /home/guest/dir1/* /home/guest/dir2/か?ワイルドカードを複数の引数に変換することで、シェルはそれを機能させます。execワイルドカードを使用してコマンドを実行すると、そのディレクトリ内のすべてのファイルではなく、文字どおりに名前がln付けられた単一のソースが検索されます。*/home/guest/dir1/

Python の同等物は次のようなものです (シェルで可能なチルダ、env 変数、コマンド置換など、2 つのレベルを一緒に混ぜて他の多くのケースを無視してもかまわない場合):

dst = args[-1]
for srcglob in args[:-1]:
    for src in glob.glob(srcglob):
        os.symlink(src, os.path.join(dst, os.path.dirname(src)))

それはできないos.symlinkからです。「名前をフィルタリングせずにfind . -name foo使用するのと同じことをしたい」と言っているようなものです。または、さらに言えば、シェルがグロビングしないos.walkのと同等のことをしたいと思っています。」ln -s /home/guest/dir1/* /home/guest/dir2/

正しい答えはglob、 、 またはfnmatch、またはos.listdirプラスの正規表現、または好みのものを使用することです。

を使用しないでください。これos.walkは、再帰的な*ファイルシステム ウォークを実行するため、シェル展開に近いものでさえありません。

于 2013-03-22T21:52:58.540 に答える
15

*あなたの場合、「で始まるすべてのファイル」を指定するシェル拡張パターンです/home/guest/dir1/

ただし、このパターンを一致するファイルに展開するのはシェルの役割です。lnコマンドのものではありません。

しかしos.symlink、これはシェルではなく、OS 呼び出しです。したがって、シェル拡張パターンはサポートされていません。スクリプトでその作業を行う必要があります。

これを行うにはos.walk、 、またはを使用できますos.listdir。他の回答に示されているように、適切な呼び出しは、何をしたいかによって異なります。(os.walkと同等ではありません*)


自分自身を納得させるために、次のコマンドを Unix マシンの端末で実行しますpython -c "import sys; print sys.argv" *。マッチングを行っているのはシェルであることがわかります。

于 2013-03-22T21:52:51.497 に答える