ファイルパスを指定するときに「/ home / username /」の代わりに「〜」を使用できないのはなぜですか


43

たとえば、ファイルを解凍するときに、ファイルパスを指す~代わりに使用できます。/home/username/.zip

ただし、今日、ターミナルでRNNの例を実行するために同じ方法に従ったとき、tensorflow.python.framework.errors_impl.NotFoundErrorスローされました。

$ python ptb_word_lm.py --data_path=~/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/simple-examples/data/ --model=small 
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcublas.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcufft.so.8.0 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:135] successfully opened CUDA library libcurand.so.8.0 locally
Traceback (most recent call last):
  File "ptb_word_lm.py", line 374, in <module>
    tf.app.run()
  File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/platform/app.py", line 44, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
  File "ptb_word_lm.py", line 321, in main
    raw_data = reader.ptb_raw_data(FLAGS.data_path)
  File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/ptb/reader.py", line 73, in ptb_raw_data
    word_to_id = _build_vocab(train_path)
  File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/ptb/reader.py", line 34, in _build_vocab
    data = _read_words(filename)
  File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/ptb/reader.py", line 30, in _read_words
    return f.read().decode("utf-8").replace("\n", "<eos>").split()
  File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/lib/io/file_io.py", line 106, in read
    self._preread_check()
  File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/lib/io/file_io.py", line 73, in _preread_check
    compat.as_bytes(self.__name), 1024 * 512, status)
  File "/home/hok/anaconda2/lib/python2.7/contextlib.py", line 24, in __exit__
    self.gen.next()
  File "/home/hok/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/errors_impl.py", line 469, in raise_exception_on_not_ok_status
    pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.NotFoundError: ~/anaconda2/lib/python2.7/site-packages/tensorflow/models-master/tutorials/rnn/simple-examples/data/ptb.train.txt

次に、に置き換えました~/home/username/、正常に機能しました。

RNNの例を実行するときに、ファイルパスを指す~代わりに使用できないのはなぜ/home/username/ですか?

詳しく教えてください。




@OskarSkog ~引数がpythonに渡される前に、シェルは展開すべきではありませんか?シェルがパス内のバックスラッシュエスケープを展開するように、またはパスが引用されている場合は引用符を削除します。
マイケルジョンソン

1
とは異なり$VARIABLES、は~文字列の先頭でのみ展開されます。
アレクシス

@OskarSkogは、問題はPythonが(拡張を実行するように機能することを不合理な期待を設定し、機能の一部を欠くに固有であることを意味し、「Pythonは何〜の手段を知っていません」の後にあることexecd「が)必要があります UNIXツールで広く利用可能であるが、 。
チャールズダフィー

回答:


45

~通常はシェルによって展開されることを理解する必要があります。あなたが呼び出すプログラムはそれを見ることはなく、bashによって挿入されたフルパス名を見ます。ただし、これは、チルダが引数の先頭にある場合にのみ発生します(引用符で囲まれていません)。

実行しているPythonプログラムがgetoptコマンドラインを解析するようなモジュールを使用している場合、--data-pathチルダ展開を許可するための別個の「単語」としてオプションの引数を指定できます。

$ python ptb_word_lm.py --data_path ~/anaconda2/lib/python2.7/...

独自のコードでは、引数処理にを使用しgetoptたりargparse、@ JacobVlijmの答えが示唆するようにチルダを手動で展開したりできます。

PS。チルダは、次のようなシェル変数割り当て式の先頭でも展開されDIRNAME=~/anaconda2ます。質問のチルダも等号に従いますが、この使用法はシェルにとって特別な意味はなく(プログラムに渡されるだけのものです)、展開をトリガーしません。


6
あなたがない限り知っている getoptすでに、使用することは、argparseあなたは、Pythonを書いている場合。
ニックT

それがargparse主な代替手段であるため、私は答えに追加しましたが、個人的にはgetopt、より簡単ではなく、使用するのがはるかに難しいと思います。YMMV。
アレクシス

33

Pythonでのチルダ展開

答えは短く簡単です:

~あなたが使用しない限り、Pythonは展開しません:

import os
os.path.expanduser('~/your_directory')

こちらもご覧ください

os.path.expanduser(path)
UnixおよびWindowsでは、〜または〜userの初期コンポーネントをそのユーザーのホームディレクトリに置き換えた引数を返します。

Unixでは、初期〜が設定されている場合、環境変数HOMEに置き換えられます。それ以外の場合、現在のユーザーのホームディレクトリは、組み込みモジュールpwdを介してパスワードディレクトリで検索されます。最初の〜userは、パスワードディレクトリで直接検索されます。


11
一般に、チルダの展開はOSレベルで行われると決して想定すべきではありません。これはUNIXシェル(すべてではありません!)が行うものです。
ファルシル

1
関連性の高い問題は、アレクシスの答え~、つまりシェル引数リスト内の位置に並んでいると思います。
デビッドフォースター

@farsil、私は同意しません。プログラムは移植可能にすることができますが、コマンドラインから実行する場合は、特定のシステムで実行します。とのは、(これはaskubuntu.comで、UbuntuがいつものUnixであることを忘れないようにしましょう、我々が知っている限り :-)
アレクシス

1
@alexis:UbuntuはOSレベルでもチルダ展開を行いません。まだシェル機能です。
user2357112

1
髪を分割していると思います。カーネルがそれを行っていると言う人はいません。要点は、引数を取るプログラムによって行われるのではないということです。
アレクシス

12

チルダ展開は、シェル間でわずかに異なるいくつかのコンテキストでのみ行われます

実行中:

var=~

または

export var=~

いくつかのシェルで。じゃない

echo var=~
env var=~ cmd
./configure --prefix=~

POSIXシェルで。

それはであるbashPOSIX準拠モードで(と呼ばれるときのようでないときけれどもshとき、またはPOSIXLY_CORRECT環境にあります):

$ bash -c 'echo a=~'
a=/home/stephane
$ POSIXLY_CORRECT= bash -c 'echo a=~'
a=~
$ SHELLOPTS=posix bash -c 'echo a=~'
a=~
$ (exec -a sh bash -c 'echo a=~')
a=~

しかし、その唯一のときの左に何=それはで展開されるだろうがそう、引用符で囲まれていない有効な変数名のような形をしているcmd prefix=~、それはでないだろうcmd --prefix=~(と--prefix有効な変数名ではありません)も中cmd "p"refix=~(そのせいで引用されたのp)も、でvar=prefix; cmd $var=~

zsh、引用符で囲まmagic_equal_subst~ていない後に展開されるオプションを設定できます=

$ zsh -c 'echo a=~'
a=~
$ zsh -o magic_equal_subst -c 'echo a=~'
a=/home/stephane
$ zsh -o magic_equal_subst -c 'echo --a=~'
--a=/home/stephane

~(の反対~user)の場合、$HOME代わりに使用できます:

cmd --whatever="$HOME/whatever"

~の値に展開されます$HOME$HOMEが設定されていない場合、動作はシェルによって異なります。一部のシェルは、ユーザーデータベースを照会します。あなたがそれを考慮したいなら、あなたはすることができます(そしてそれはあなたがする必要があることでもあります~user):

dir=~ # or dir=~user
cmd --whatever="$dir/whatever"

いずれにしても、zsh覚えている以外のシェルでは、変数展開を引用する必要があります!


1
Bashのリファレンスマニュアルでは、チルダは変数の割り当てと単語の先頭でのみ展開されると言われてecho a=~いるようです。したがって、展開するとマニュアルと矛盾するようです。
-ilkkachu

@ilkkachu、はい、マニュアルは不完全です。また、どのコンテキスト~で展開されるか( "単語"の意味)を明確に指定しません。詳細については、回答の上部にあるリンクを参照してください。
ステファンシャゼラス

6

~あなたのコマンドが満たしていない特定の拡張ルールがあります。具体的には、引用符で囲まれていない場合にのみ、単語の先頭(例python ~/script.py)または変数の割り当ての先頭(例PYTHONPATH=~/scripts python script.py)で展開されます。あなたが持っているのは --data_path=~/blabla、シェル用語では1つの単語であるため、展開は実行されません。

すぐに修正できるのは$HOME、通常の変数展開ルールに従うシェル変数を使用することです。

python ptb_word_lm.py --data_path=$HOME/blabla

それは少し単純化しすぎています。チルダの展開がのように実行された他のコンテキストがありますPATH=$PATH:~/bin。また、$HOME引用符で囲む必要があるか、split + globが以外のシェルに適用されzshます。
ステファンシャゼル

@sch申し訳ありませんが、コメントで提供したリンクは、光学式マウスに関する質問につながります。チルダの拡張については言及していません。説明してもらえますか?
セルギーコロディアズニー

いい答えだ。このセクションbashでは、基本的にマニュアルの状態を要約していTilde Expansionます。+1
セルギーコロディアズニー

申し訳ありませんが、unix.SEでサイト内リンクを使用することに慣れているのは[link](/a/146697)、ここの別のサイトにいることに気付かなかったからです。リンクはにする必要があります
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.