एक पथ के लिए उपसर्ग के रूप में उपयोग किए जाने पर एक ~ (टिल्ड) क्या है?


11

संपादित करें: यह /programming/998626/meaning-of-tilde-in-linux-bash-not-home-directory/ का एक डुप्लिकेट है । मेरे पास इस प्रश्न को डुप्लिकेट के रूप में बंद करने की प्रतिष्ठा नहीं है।

मैं ~होम डाइरेक्टरी में इसका उल्लेख नहीं कर रहा हूँ , बल्कि यह है:

$ ls ~foo/bar
/some/mount/point/foo/bar

हालाँकि अगर मैं इसे एक अलग माउंट पॉइंट के साथ आज़माता हूँ, जैसे:

$ mount | ag "/dev "
devfs on /dev (devfs, local, nobrowse)
$ ls /dev/stdin
/dev/stdin
$ ls ~stdin
zsh: no such user or named directory: stdin . 
# bash has a similar error message: 
ls: ~stdin: No such file or directory

~इस संदर्भ में क्या कहा जाता है? यह कैसे काम करता है?

संपादित करें: नीचे दी गई कुछ टिप्पणियों के आधार पर अधिक जानकारी:

  1. मैं यह प्रमाणित कर सकता हूं कि fooमेरे सिस्टम पर कोई उपयोगकर्ता नाम नहीं है।
  2. स्वत: पूर्ण होने का प्रयास करते समय ls -lah ~सभी विकल्प नहीं दिखाए जाते हैं। cd ~quxजब मैं quxस्वत: पूर्ण नहीं दिखाता , तो मैं सक्षम हूं । फिर quxसे मेरे सिस्टम में एक उपयोगकर्ता नहीं है।
  3. अगर यह मायने रखता है /some/mount/pointकि एक नेटवर्क शेयर है।
  4. सभी विवरण कुछ नामित पथ नामावली, पथ नाम विस्तार की एक Z शेल सुविधा का सुझाव देते हैं, लेकिन यह बाश में भी काम करता है, जो जाहिरा तौर पर जेड शेल के नामित पथ जैसी चीजों का समर्थन नहीं करता है।

5
~fooउपयोगकर्ता की होम डायरेक्टरी है foo। यदि उपयोगकर्ता निर्दिष्ट नहीं है, तो वर्तमान उपयोगकर्ता डिफ़ॉल्ट है।
डोपघोटी

लेकिन इस मामले में, /some/mount/pointनिश्चित रूप से मेरे घर निर्देशिका नहीं है। cd ~करने के लिए मुझे ले जाता है /Users/$username/--which मैचों$HOME
आरडी

1
zshनामित निर्देशिकाओं को इंगित करने के लिए टिल्ड का उपयोग करना भी प्रतीत होता है।
डोपघोटी

मुझे उस पर भी शक हुआ !! कुछ कारणों को छोड़कर मैंने ऊपर जिन कमांडों को पोस्ट किया है, वे बैश में भी काम करते हैं ( bash -c "ls ~foo/bar") - जिसमें डायरेक्ट्रीज़ का नाम नहीं है। इसके अलावा, अगर मैं निरीक्षण करता हूं, तो मैं envकिसी भी नामित निर्देशिका को नहीं देखता हूं। मैं मैक ओएस पर हूं और मुझे लगता है कि यह ओएस एक्स के लिए विशिष्ट कुछ विशेषता है।
आरडी

1
आपने ही कहा था ~foo। वास्तविक स्ट्रिंग लें (उदाहरण नहीं foo) और करें grep "actual username" /etc/passwd। bash मैनुअल के अनुसार ~textकेवल संभव लॉगिन उपयोगकर्ता नाम के लिए काम करना चाहिए (जरूरी नहीं कि यह वास्तव में लॉग इन करने में सक्षम है ~lp, उदाहरण के लिए, सिस्टम उपयोगकर्ताओं के मामले में )। मेरे सभी परीक्षणों में, उपयोगकर्ता नाम होने के ~stringसाथ मेल खाती है string
सर्गी कोलोडियाज़नी

जवाबों:


14

क्या है ~ फू

बैश मैनुअल से उद्धरण (अतिरिक्त जोर के साथ):

यदि कोई शब्द एक अनछुए टिल्ड वर्ण (`~ ~) के साथ शुरू होता है, तो पहले निर्विवाद स्लेश (या यदि कोई अछूता स्लेश नहीं है) से पहले के सभी वर्ण टिल्ड-प्रीफ़ेक्चर माने जाते हैं। टिल्ड-प्रीफ़िक्स को उद्धृत किया जाता है, टिल्ड के बाद टिल्ड-प्रीफ़िक्स के पात्रों को एक संभावित लॉगिन नाम के रूप में माना जाता है ।

~foofooमें निर्दिष्ट के रूप में उपयोगकर्ता के घर निर्देशिका के लिए फैलता है /etc/passwd। ध्यान दें, इसमें सिस्टम उपयोगकर्ता नाम शामिल हो सकते हैं; यह जरूरी नहीं है कि मानव उपयोगकर्ता या वे वास्तव में स्थानीय रूप से लॉग इन कर सकते हैं (वे उदाहरण के लिए SSH कुंजी के माध्यम से लॉग इन कर सकते हैं)।

वास्तव में, जैसा कि टिप्पणियों में कहा गया है , फ़ंक्शन का bashउपयोग करेगा getpwnam। यह फ़ंक्शन स्वयं POSIX मानक द्वारा निर्दिष्ट है , इसलिए अधिकांश यूनिक्स जैसी प्रणालियों पर मौजूद होना चाहिए, जिसमें macOS X भी शामिल है । यह फ़ंक्शन /etc/passwdकेवल तक सीमित नहीं है और LDAP और NIS जैसे अन्य डेटाबेस को खोजता है। bash स्रोत कोड से विशेष अंश , tilde.cफ़ाइल, लाइन 394 पर शुरू:

  /* No preexpansion hook, or the preexpansion hook failed.  Look in the
     password database. */
  dirname = (char *)NULL;
#if defined (HAVE_GETPWNAM)
  user_entry = getpwnam (username);
#else
  user_entry = 0;

व्यावहारिक उदाहरण

नीचे आप मेरे सिस्टम पर सिस्टम उपयोगकर्ता नाम के साथ परीक्षण देख सकते हैं। इसी passwdप्रविष्टि और परिणाम पर ध्यान देंls ~username

$ grep '_apt' /etc/passwd
_apt:x:104:65534::/nonexistent:/bin/false
$ ls ~_apt
ls: cannot access '/nonexistent': No such file or directory
$ grep '^lp' /etc/passwd
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
$ ls ~lp
ls: cannot access '/var/spool/lpd': No such file or directory

भले ही उदाहरण के लिए _aptखाता बंद कर दिया गया हो, passwd -S aptलेकिन इसका उत्पादन अभी भी संभव लॉगिन नाम के रूप में दिखाया जा रहा है:

_apt L 11/29/2017 0 99999 7 -1

कृपया ध्यान दें: यह macOS विशिष्ट विशेषता नहीं है, बल्कि शेल-विशिष्ट सुविधा है।


मुझे संदेह है कि शेल खाता समाप्ति तिथि के बारे में कुछ भी पता लगाने पर निर्भर कर सकता है या यदि यह टिल्ड का विस्तार करते समय लॉक या कुछ भी है। जैसे कि लिनक्स पर, समाप्ति की तारीख को /etc/shadowपासवर्ड की तरह अन्य संरक्षित प्रमाणीकरण सूचनाओं के साथ संग्रहित किया जाता है । इसमें संदर्भ passwdसिर्फ पासवर्ड को अमान्य बनाने के बारे में है: जो अन्य माध्यमों से प्रमाणीकरण को नहीं रोक सकेगा।
ilkachachu

@ilkachachu हां, आप सही कह रहे हैं। मैंने testuserपासवर्ड समाप्ति तिथि जोड़ने और संशोधित करने के साथ परीक्षण किया है । उपयोगकर्ता नाम अभी भी टैब पूरा होने में दिखाई देता है। मैंने उत्तर से उस बिट को हटा दिया है
सर्गी कोलोडाज़नी

1
इस जवाब के साथ एकमात्र समस्या यह है कि यह bashमैन पेज को उद्धृत करता है (और उस पर पुराना है, ऐसा लगता है)। ओपी वास्तव में उपयोग कर रहा है zsh(स्पष्ट हो सकता था), हालांकि टिप्पणियों में यह उल्लेख किया गया है कि bashएक ही व्यवहार है।
केन वेन वांडरलिंडे

2
आप शेल के रूप में समान लुकअप मेकेनिज्म का पालन getent passwd fooकरने के grep foo /etc/passwordलिए उपयोग कर सकते हैं - शायद नेटवर्क-आधारित निर्देशिका सेवाओं सहित जिसमें @Aigigail उल्लेख है।
आरजेहंटर

1
'जैसे कि LDAP और NIS' बिट के लिए उत्तर के रूप में स्वीकार किया जाता है, जो मेरे मामले में सही हो रहा है!
आरडी

5

सारांश में कि आप कुछ के लिए क्यों देख रहे हैं ~foo/bar, ऐसा इसलिए है क्योंकि आपके पास fooसिस्टम में एक उपयोगकर्ता है जिसका नाम barउनके होम डायरेक्टरी में फ़ोल्डर के साथ है ।

इस समाधान को दूसरे समुदाय में देखें जो बताता है कि (टिल्ड) ~सिर्फ "होम डायरेक्टरी" से अधिक क्यों है।

यदि आपके पास binआपके सिस्टम पर एक उपयोगकर्ता नाम है, तो आप बिन होम डायरेक्टरी की सामग्री को कमांड द्वारा सूचीबद्ध कर सकते हैं :

ls ~bin

एक और चीज जो आप आजमा सकते हैं, वह है कि एक प्रॉम्प्ट पर निम्नलिखित टाइप करने के बाद टैब को पूरा करने का उपयोग करें (गाड़ी वापस न करें, बस टैब कुंजी का उपयोग करें):

ls -lah ~ tab

~यदि आप जारी रखते हैं, तो उपयोगकर्ताओं की होम निर्देशिकाओं की सूची का विस्तार करना। उदाहरण (छंटनी) टैब समापन का आउटपुटls -lah ~ tab

$ ls -lah ~ [tab]
~antman/            ~games/
~bin/               ~mail/

1
टैब पूरा होने के लिए +1। यह स्पष्ट रूप से उन सभी उपयोगकर्ता नामों को प्रकट करता है जो बैश से संभव लॉगिन नाम प्राप्त कर सकते हैं /etc/passwd। यह तुरंत स्पष्ट करने में मदद करता है कि क्या हो रहा है यदि उपयोगकर्ता के पास सिस्टम पर मौजूद उपयोगकर्ता नामों के बारे में पता है।
सर्गी कोलोडियाज़नी

2
बैश पूरा होने पर टिप के लिए धन्यवाद - कुछ दिलचस्प स्वत: पूर्ण परिणाम हुए। जबकि ~fooस्वत: पूर्ण किया था, मैं यह प्रमाणित करते हैं कर सकते हैं कि fooअपने सिस्टम पर एक उपयोगकर्ता नहीं है (और वास्तव में में मौजूद नहीं है /etc/passwd)। इसके अलावा, सभी फ़ोल्डर / फाइलें /some/mount/pointस्वतः पूर्ण में दिखाई देती हैं जो सुपर दिलचस्प है।
आरडी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.