![为什么在提供文件路径时不能使用“ ~ ”而不是“ /home/username/ ”](https://linux22.com/image/1059492/%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8%E6%8F%90%E4%BE%9B%E6%96%87%E4%BB%B6%E8%B7%AF%E5%BE%84%E6%97%B6%E4%B8%8D%E8%83%BD%E4%BD%BF%E7%94%A8%E2%80%9C%20~%20%E2%80%9D%E8%80%8C%E4%B8%8D%E6%98%AF%E2%80%9C%20%2Fhome%2Fusername%2F%20%E2%80%9D.png)
我可以使用~
而不是/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/
来指向文件路径?
你能详细告诉我吗?
答案1
您需要了解,~
shell 通常会扩展它;您调用的程序永远看不到它,它们看到的是 bash 插入的完整路径名。但这仅当波浪号位于参数开头(且未加引号)时才会发生。
如果您正在运行的 Python 程序使用类似的模块getopt
来解析其命令行,则可以将选项的参数--data-path
作为单独的“单词”以允许波浪号扩展:
$ python ptb_word_lm.py --data_path ~/anaconda2/lib/python2.7/...
在您自己的代码中,您可以使用getopt
或argparse
进行参数处理,也可以按照@JacobVlijm 的回答所建议的那样手动扩展波浪号。
PS. 波浪号在开头也会展开壳变量赋值表达式如DIRNAME=~/anaconda2
;虽然你问题中的波浪号也跟在等号后面,但是这种用法对 shell 来说没有特殊含义(它只是传递给程序的东西)并且不会触发扩展。
答案2
Python 中的波浪符号扩展
答案很简单:
~
除非您使用以下命令,否则python 不会扩展:
import os
os.path.expanduser('~/your_directory')
也可以看看这里:
os.path.expanduser(路径)
在 Unix 和 Windows 上,返回以 ~ 或 ~user 为初始组件的参数,并将其替换为该用户的主目录。在 Unix 上,如果设置了环境变量 HOME,则以 ~ 开头的字符替换该变量;否则,将通过内置模块 pwd 在密码目录中查找当前用户的主目录。将直接在密码目录中查找以 ~user 开头的字符。
答案3
波浪号扩展仅在少数情况下进行,且在不同的 shell 中略有不同。
虽然它在以下情况下执行:
var=~
或者
export var=~
在一些 shell 中。它不在
echo var=~
env var=~ cmd
./configure --prefix=~
在 POSIX shell 中。
bash
但是当不处于 POSIX 符合模式时(例如当被调用为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
未设置 ,则行为因 shell 而异。有些 shell 会查询用户数据库。如果您想考虑到这一点,您可以这样做(这也是您必须对 执行的操作~user
):
dir=~ # or dir=~user
cmd --whatever="$dir/whatever"
无论如何,除了zsh
记住之外,在 shell 中你需要引用变量扩展!
答案4
~
具有特定的扩展规则,而您的命令不满足这些规则。具体来说,它仅在未加引号时才会扩展,无论是在单词的开头(例如python ~/script.py
)还是在变量赋值的开头(例如PYTHONPATH=~/scripts python script.py
)。您所拥有的 --data_path=~/blabla
是在 shell 术语中为单个单词,因此不会执行扩展。
立即修复的方法是使用$HOME
shell 变量,它遵循常规变量扩展规则:
python ptb_word_lm.py --data_path=$HOME/blabla