Dosya yolunu verirken neden '/ home / username /' yerine '~' kullanamıyorum


43

Örneğin bir dosyayı açarken bir dosya yolunu işaret etmek ~yerine kullanabilirim ./home/username/.zip

Ancak bugün terminalde bir RNN örneği çalıştırmak için aynı yolu takip ettiğimde tensorflow.python.framework.errors_impl.NotFoundErroratıldı.

$ 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

Sonra ~ile değiştirdim /home/username/ve düzgün çalıştı.

Bir RNN örneği çalıştırırken neden dosya yolunu işaret etmek ~yerine kullanamıyorum /home/username/?

Bana ayrıntılı olarak söyleyebilir misiniz?




@OskarSkog Argüman python'a iletilmeden ~önce kabuk genişlememeli mi? Tıpkı kabuğun yoldaki ters eğik çizgileri uzatması veya yolun kote edilmesi halinde tırnak işaretleri kaldırması gibi.
Micheal Johnson,

1
Aksine $VARIABLES, ~sadece bir dizgenin başlangıcında genişletilir.
alexis

@OskarSkog bir sorun Python (genişleme gerçekleştiren böyle bir işlevsellik de mantıksız bir beklenti kurma, işlevsellik bir parça eksik özgü olduğunu ima "Python neyi ~ aracı bilmez" sonra olmak execd') olmalıdır UNIX araçları yaygın satışa sunulacak .
Charles Duffy

Yanıtlar:


45

Bunun ~normal olarak kabuk tarafından genişletildiğini anlamanız gerekir ; aradığınız programlar onu asla görmezler, tam yol adını bash tarafından eklenen şekilde görürler. Ancak bu, yalnızca tilde bir argümanın başlangıcında olduğunda (ve alıntı olmadığında) olur.

Çalıştırmakta olduğunuz Python programı getoptkomut satırını ayrıştırmak gibi bir modül kullanıyorsa , --data-pathtilde genişlemesine izin vermek için seçeneğin ayrı bir "kelime" olarak argümanını verebilirsiniz:

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

Kendi kodunuzda, argüman işleme için getoptveya argparseargüman işleme için kullanabilirsiniz ve ayrıca @ JacobVlijm'in önerdiği gibi tildeleri manuel olarak da genişletebilirsiniz.

PS. Tilde, aynı zamanda gibi bir kabuk değişken atama ifadesinin başlangıcında genişletilir DIRNAME=~/anaconda2; Sorunuzdaki tilde de eşittir işaretini takip etse de, bu kullanımın kabuk için özel bir anlamı yoktur (yalnızca bir programa iletilen bir şeydir) ve genişlemeyi tetiklemez.


6
Eğer sürece biliyor getopt zaten, kullanım argparsePython yazıyorsanız.
Nick T

Bu argparsesorunun cevabını ana alternatif olduğu için ekledim , fakat şahsen kullanımını daha getoptkolay değil, daha zor buluyorum . YMMV.
alexis

33

Pitonda tilde genişlemesi

Cevap kısa ve basittir:

python, ~kullanmadığınız sürece genişlemez :

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

Ayrıca buraya bakınız :

os.path.expanduser (yol)
Unix ve Windows'ta, argümanı bu kullanıcının ana dizini tarafından değiştirilen ~ veya ~ kullanıcı ilk bileşeniyle döndürün.

Unix'te, başlangıç ​​~ ayarlanmışsa çevre değişkeni HOME ile değiştirilir; Aksi halde mevcut kullanıcının giriş dizini şifre dizini içinde yerleşik modül pwd üzerinden aranır. Bir ilk ~ kullanıcı doğrudan şifre dizininde aranır.


11
Genelde, tilde genişlemesinin bir işletim sistemi seviyesinde yapıldığını asla varsaymamalısınız, unix kabukları (hepsi değil!) Sizin için yapar.
farsil

1
Sanırım daha alakalı olan sorun Alexis'in cevabında sıralandı: ~kabuk tartışma listesindeki yeri.
David Foerster

@farsil, katılmıyorum. Programlar taşınabilir hale getirilebilir, ancak bunları komut satırından çalıştırdığınızda, bunu belirli bir sistemde yaparsınız. Unutmayalım ki bu askubuntu.com ve Ubuntu her zaman Unix ( bildiğimiz kadarıyla :-)
alexis

1
@alexis: Ubuntu işletim sistemi düzeyinde de genişleme yapmaz. Hala kabuk işlevi var.
user2357112

1
Metnin saçları ayırdığına inanıyor. Kimse çekirdeğin yaptığını söylemedi. Mesele şu ki, tartışmayı alan program tarafından yapılmadı.
alexis

12

Tilde genişlemesi, mermiler arasında hafifçe değişen birkaç bağlamda yapılır .

Gerçekleştirilirken:

var=~

Veya

export var=~

Bazı mermilerde. İçinde değil

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

POSIX kabukları içinde.

Bu ise basholsa değilken POSIX uygunluk modunda (olarak adlandırılan zaman gibi sh, ya da ne zaman POSIXLY_CORRECTortamdaysa):

$ 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=~

Ancak bu, yalnızca solundaki =şey, kote cmd prefix=~edilmemiş geçerli bir değişken adı şeklinde şekillendiğinde ortaya çıkar, bu yüzden de genişletilirken , içinde cmd --prefix=~( --prefixgeçerli bir değişken ismi olmadığı için), ne de cmd "p"refix=~(çünkü p) içinde var=prefix; cmd $var=~.

İçinde belirtilmemiş herhangi bir işlemden sonra genişletme seçeneğini zshayarlayabilirsiniz .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

Durumunda ~(aksine ~user), sadece kullanabilirsiniz $HOME:

cmd --whatever="$HOME/whatever"

~değerine genişler $HOME. Eğer $HOMEayarlanmamış, davranış kabuk arasında değişir. Bazı mermiler kullanıcı veritabanını sorgular. Bunu hesaba katmak istersen, yapabilirsin (ve bunun için yapman gereken de buydu ~user):

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

Her durumda, zshhatırlamaktan başka kabuklarda değişken açılımlar yapman gerek!


1
Bash'in referans el kitabı , tildlerin sadece değişken ödevlerde ve bir kelimenin başlangıcında genişletildiğini gösteriyor, bu yüzden onu genişletmek echo a=~el kitabına aykırı görünüyor.
ilkkachu

@ ilkkachu, evet bu kılavuz eksik. Ayrıca hangi bağlamda ~genişletileceğini de açıkça belirtmiyor ("kelime" ile ne kastedilmektedir). Daha fazla bilgi için cevabın üst kısmındaki linke bakınız.
Stéphane Chazelas

6

~Komutunuzun karşılamadığı özel genişleme kurallarına sahip. Spesifik olarak, sadece bir kelimenin başlangıcında (örn. python ~/script.py) Veya değişken atamanın başlangıcında (örneğin ) alıntı yapıldığında genişletilir PYTHONPATH=~/scripts python script.py. Sahip olduğunuz şey, --data_path=~/blablakabuklu terimlerle tek bir kelimedir, bu nedenle genişleme gerçekleştirilmez.

Hemen yapılan düzeltme, $HOMEnormal değişken genişletme kurallarını izleyen kabuk değişkenini kullanmaktır :

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

Bu biraz fazla basitleştirilmiş, tilde genişlemenin olduğu gibi yapıldığı başka bağlamlar da varPATH=$PATH:~/bin . Ayrıca $HOMEalıntılanması veya bölünmesi gereken + glob dışındaki kabuklarda da geçerlidir zsh.
Stéphane Chazelas

@sch üzgünüm, ancak yorumda verdiğiniz bağlantı, tilde genişlemesinden söz etmeden, optik fare hakkında bir soruya yol açıyor. Lütfen bunu açıklayabilir misiniz?
Sergiy Kolodyazhnyy

İyi cevap. Bu bölümde bash, kılavuzun el kitabında belirtilenleri özetlemektedir Tilde Expansion. +1
Sergiy Kolodyazhnyy

Üzgünüz, unix içindeki site içi bağlantıları kullanmaya çok alışkınım. Burada olduğu gibi [link](/a/146697)farklı bir sitede olduğumuzu bilmiyordum. Bağlantı orada
Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.