ग्लोबिंग के लिए बैश में क्या सेटिंग है, यह नियंत्रित करने के लिए कि क्या * डॉट फाइलें मेल खाती हैं


12

मुझे हाल ही में आश्चर्य हुआ जब मैंने कुछ ऐसा किया mv ./* ../somedirectory और पाया कि जैसी फाइलें .gitignoreस्थानांतरित नहीं हुई थीं।

मैं अपना अधिकांश काम OS X पर zsh में करता हूं, और मुझे यह आश्चर्यचकित करता है कि मैं CentOS पर बैश हूं। मैंने ओएस एक्स पर बैश की कोशिश की और एक ही व्यवहार पाया: *डॉट फ़ाइलों से मेल नहीं खाता। यह मेरे लिए बहुत अवांछनीय लगता है, लेकिन जाहिर है यह बैश डिफ़ॉल्ट है। (यह मेरे द्वारा याद किए गए सभी के लिए भी zsh डिफ़ॉल्ट हो सकता है, लेकिन मैंने इसे अपने .zshrc में वर्षों पहले बदल दिया था और यह भूल गया कि यह कभी भी अलग तरह से काम करता है।)

मैं अपेक्षा के अनुसार व्यवहार करने के लिए bash को कैसे कॉन्फ़िगर कर सकता हूं: सभी फ़ाइलों से मिलान करने के लिए *, और डॉट फ़ाइलों की उपेक्षा न करें।

मामले में यह बिल्कुल स्पष्ट नहीं है, यहां इसे कैसे पुन: पेश किया जाए

cd /tmp
mkdir {t,d}est
touch test/{.,}{1,2,3,4,5,6,7}
ls -hal test
mv test/* dest
ls -hal test     # notice dot files are still there
ls -hal dest     # notice only some files were mv'ed


हाँ, वे संबंधित हैं। जब मैंने खोजा तो वह नहीं दिखा (शायद इसलिए कि प्रश्नकर्ता ने ग्लोबिंग या डॉट फ़ाइलों का उल्लेख नहीं किया है), लेकिन यह वास्तव में एक अलग प्रश्न है। वह पूछ रहा था कि फ़ाइलों को कैसे स्थानांतरित किया जाए, और मैं पूछ रहा था कि शेल व्यवहार को कैसे बदलना है, और विशेष रूप से बैश के लिए। मैंने यह नहीं पूछा कि क्या यह प्रश्न मेरे लिए दिखा था (क्योंकि आपके अत्यंत पूर्ण और पूरी तरह से उत्तर में बैश सेटिंग शामिल है), लेकिन यह अभी भी एक अलग प्रश्न है, और कोई व्यक्ति मेरे प्रश्न का उत्तर ढूंढने के लिए जरूरी नहीं है। उसका सवाल।
आइकनोक्लास्ट

यह पूरी तरह से "मेरे सवाल का जवाब तलाशने वाला कोई व्यक्ति जरूरी नहीं है कि उसका सवाल हो" व्यवसाय बिल्कुल वैसा ही है जैसे हमारे पास डुप्लिकेट के साथ प्रश्नों को बंद करने का तरीका है।
गाइल्स का SO- बुराई पर रोक '22

हां, लेकिन आपको मुख्य बिंदु याद आ रहा है, जो यह है कि यह एक अलग प्रश्न है
iconoclast

जवाबों:


14

दे घुमा के

जैसा कि आपने पहले ही देखा .है कि नाम या स्लैश की शुरुआत में बैश मैच नहीं करेगा । बिंदु से संबंधित मिलान को बदलने के लिए आपको dotglobविकल्प सेट करना होगा - मैन बैश :

डॉटग्लोब यदि सेट किया जाता है, तो बैश में एक `के साथ शुरू होने वाले फ़ाइल नाम शामिल होते हैं। में
    pathname विस्तार के परिणाम।

बैश उपयोग के साथ इसे सक्षम / सेट करने के लिए shopt, जैसे:

shopt -s dotglob


Zsh के लिए आप dotglobविकल्प का उपयोग भी कर सकते हैं लेकिन आपको setoptइसे सक्षम करने के लिए उपयोग करना होगा, जैसे:

setopt dotglob

2
zshबेहतर विकल्प के साथ , प्रति-ग्लोब के आधार पर डॉटग्लोब को सक्षम करना है :mv test/*(D) /dest
स्टीफन चेज़लस

7

मैंने इसका परीक्षण किया और यह समस्या हल करती है:

shopt -s dotglob

आउटपुट:

~/stackexchangeanswers/40662$ ls -hal dest
total 8.0K
drwxr-xr-x 2 jodiec jodiec 4.0K 2012-06-12 22:15 .
drwxr-xr-x 4 jodiec jodiec 4.0K 2012-06-12 22:15 ..
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 1
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 .1
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 2
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 .2
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 3
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 .3
...snipped....

क्षमा करें, लेकिन उलरिच ने पहले उत्तर दिया।
इकोनॉस्टल

3
हम सब एक ही टीम में हैं। यह ठीक है।
जोड़ी सी

6

*एक गोला है जो शेल द्वारा विस्तारित है। डिफ़ॉल्ट शेल में वे फ़ाइलें शामिल नहीं होती हैं जिनका नाम .(छिपी हुई फ़ाइलें या डॉटफ़ाइल्स कहा जाता है) से शुरू होता है जब तक कि प्रमुख .शाब्दिक रूप से दर्ज नहीं किया जाता है।

*या [.]*या ?*या *.*या dir/*dotfiles शामिल नहीं होंगे।

.*या dir/.*होगा।

तो आप कर सकते हैं:

mv -- * .* /dest/

हालांकि कुछ गोले bash(लेकिन नहीं zsh, mkshन ही fish) में वह मिसफिट है जिसमें .*शामिल है कि- .और ..विशेष निर्देशिका प्रविष्टियों को शामिल करना, जो आप यहां नहीं चाहते हैं (और आम तौर पर कभी भी ग्लोब को शामिल नहीं करना चाहते हैं यही कारण है कि मैं इसे मिसफिट्योर कहता हूं)।

इस कारण से, आप पाएंगे कि कभी-कभी लोग (बॉर्न-जैसे गोले में) का उपयोग करते हैं:

mv -- * .[!.]* ..?* /dest/

यह तीन ग्लोब है, पहली एक मेल नॉन-हिडन फाइल, दूसरा एक फाइलनेम जिसके .बाद एक कैरेक्टर के अलावा दूसरा .और तीसरा एक फाइलनाम ..जिसके साथ कम से कम एक कैरेक्टर शुरू होता है।

हालाँकि कुछ आधुनिक गोले इसके आसपास बेहतर तरीके हैं

zsh

इसके साथ zsh, आप यह (D)निर्दिष्ट करने के लिए ग्लोब क्वालिफायर का उपयोग कर सकते हैं कि ग्लोब में डॉटफ़ाइल्स शामिल होना चाहिए:

mv -- *(D) /dest/

zshयह भी तय किया कि बॉर्न शेल के अन्य मिसफिट, यदि पैटर्न से मेल नहीं खाता है, तो mvकमांड नहीं चलती है।

जैसा कि ऊपर कहा गया है कि यह भी कभी नहीं शामिल होगा .और न ही ..अपने दस्ताने में, इसलिए

mv -- * .* /dest/

सुरक्षित रहेगा। हालाँकि, यदि कोई फ़ाइल मिलान *नहीं है या .*कमांड से मेल खाती कोई फ़ाइल निरस्त नहीं की जाएगी, तो इसका उपयोग करना बेहतर होगा:

mv -- (*|.*) /dest/

कुछ अन्य गोले की तरह, आप सभी ग्लब्स को भी डॉटफिल्स में शामिल करने के लिए मजबूर कर सकते हैं (उदाहरण के लिए यदि आप खुद चाहते हैं कि डॉटफाइल्स को अधिक बार शामिल किया जाए):

setopt dotglob

या:

set -o dotglob

उसके बाद, यदि आप एक विशेष ग्लोब चाहते नहीं dotfiles शामिल करने के लिए, आप इसे लिख सकते हैं:

echo *(^D)

या:

echo [^.]*

दे घुमा के

दुर्भाग्य से bashग्लोब क्वालिफायर नहीं है। तो आप विश्व स्तर पर dotfile समावेश को सक्षम करने से बचे हैं। में bash, वाक्य रचना है:

shopt -s dotglob

(और [^.]*छिपी हुई फ़ाइलों के बिना ग्लब्स के लिए उपयोग करें)।

के साथ dotglob, bash.ही ..जैसे ग्लब्स में शामिल नहीं है *, लेकिन अभी भी ग्लब्स जैसे के लिए करता है .*

यदि आप GLOBIGNOREचर को कुछ गैर-रिक्त पर सेट करते हैं , तो यह स्वचालित रूप से dotglobविकल्प को शामिल करता है .और ग्लोब ..से और बाहर .*नहीं बल्कि लोगों ( dir/.*या .*/file!) से सक्षम करता है ताकि सुरक्षा की व्यवस्था बहुत बेकार हो। तुम कर सकते हो GLOBIGNORE='*/.:*/..:./*:../*:*/./*:*/../*', लेकिन फिर यह कैसा globs टूट जाएगा */.या ./*या ../*

एक बेहतर काम के आसपास का उपयोग करने के लिए है [.]*या dir/[.]*या [.]*/file(के साथ dotglobसक्षम) को छोड़कर dotfiles विस्तार करने के लिए .और ..

मछली

fishग्लब्स में शामिल नहीं है और .न ही ..। जब कोई मिलान नहीं होता है, तो संस्करण के आधार पर, यह या तो zsh(या bash -o failglob) या की तरह काम करेगा bash -o nullglob

mv -- * .* /dest/

यदि छिपी हुई और गैर-छिपी हुई दोनों फाइलें हैं तो काम करेंगे। अन्यथा, YMMV और कुछ संस्करणों के साथ, mv -- /destअगर कोई फ़ाइल नहीं है तो यह कॉल कर सकता है ।

ksh93

दोनों में कोई ग्लोब क्वालिफायर नहीं ksh93। आप ग्लोब में dotfiles को शामिल कर सकते हैं:

FIGNORE='@(.|..)'

के विपरीत bashहै GLOBIGNORE, कि ठीक से किया है और यह भी है की समस्या का समाधान होता .*सहित .और ..

यश

yashएक dot-globविकल्प ( set -o dot-glob) है, लेकिन इसके विपरीत bash, ग्लोब विस्तार (भी *) शामिल हैं .और ..इसलिए यह बहुत बेकार है।

tcsh

set globdot

में की तरह काम करता है bash, जो है *सिवाय डॉट फ़ाइलों में शामिल हैं .और ..लेकिन .*अभी भी शामिल है .और ..(और आप उपयोग कर सकते हैं [.]*को छोड़कर छिपा फ़ाइलों का विस्तार करने .और ..)।


4

मैचिंग डॉट फाइल्स को प्रिंट करने के लिए बैश में सबसे आसान तरीका, अनदेखा करना .और ..:

$ GLOBIGNORE=/+/
$ printf '%s\n' *


परीक्षा करना:

$ cd tmp; mkdir empty; cd empty; touch {,.}{a..h}
$ GLOBIGNORE=/+/
$  ls *
a  .a  b  .b  c  .c  d  .d  e  .e  f  .f  g  .g  h  .h

इसने सभी फाइलों को डॉट्स के साथ मुद्रित किया या नहीं, के उल्लेखनीय अपवाद के साथ .और ..

आपका उदाहरण भी सही ढंग से काम करेगा:

$ cd /tmp; mkdir {t,d}est; touch test/{,.}{a..h}
$ mv test/* dest/
$ ls -a test
.  ..
$ ls -a test/*
ls: cannot access test/*: No such file or directory

इस बात से फाइलों का खाली होना।
सिस्टम फाइलें . ..अभी भी मौजूद हैं, लेकिन एक शेल विस्तार (* का उपयोग करके) उन्हें शामिल नहीं करेगा।

और गंतव्य इनलेशन डायरेक्टरी में सभी फाइलें शामिल हैं:

$ cd dest
$ ls -a *
a  .a  b  .b  c  .c  d  .d  e  .e  f  .f  g  .g  h  .h

क्यों?

यह काम करता है क्योंकि GLOBIGNORE सेट करने के इस दुष्प्रभाव हैं:

  • shopt -s dotglobविस्तार पर डॉट डॉट फाइलें गणित डॉट डॉट ( ) पर सेट करें ।
  • फ़ाइल नाम . और ..अनदेखा किया जाता है जब GLOBIGNORE सेट किया गया है और शून्य नहीं है।

मैनुअल में विवरण LESS=+'/The GLOBIGNORE' man bash:।

इसके अलावा, हमें एक नाम रखने के लिए वैरिएबल GLOBIGNORE को सेट करने की आवश्यकता है, जिसका कोई भी फ़ाइल नाम मेल नहीं खा सकता है:
एक स्लैश (और कुछ और डबल एहतियात के रूप में)।

$ GLOBIGNORE=/+/

यह भी उपयोगी हो सकता है कि नलग्लोब को सेट किया जा सकता है, *जब मिलान करने के लिए कोई फ़ाइल नहीं होने से बचने की आवश्यकता होती है *


0

GLOBIGNORE = / + / @ user79743 की इस सेटिंग में बहुत रुचि है

मेरे अनुभव से unsetting dotglob है बुरा व्यापार लगभग सभी अपने आदेश (सीपी, mv आदि), लेकिन एक ही सच है करने के लिए स्थापित करने nullglob (विशेष रूप से नियमित अभिव्यक्ति है कि तब से बचने की जरूरत है के साथ!)।

फिर भी, यदि आपको उन्हें अपने कार्यक्रम की शुरुआत में सेट करने की आवश्यकता है, लेकिन विशिष्ट भागों में हस्तक्षेप करें जहां आप कमांड जैसे कि सीपी, एमवी आदि कहते हैं या नियमित अभिव्यक्ति का उपयोग करते हैं तो बस यह करें:

  # set dotglob, unset nullglob AFTER this
  is_nullglob=$( shopt -s | egrep -i '.*nullglob' )
  is_dotglob=$( shopt -s | egrep -i '.*dotglob' )
  [[ $is_nullglob ]] && shopt -u nullglob
  [[ ! $is_dotglob ]] && shopt -s dotglob
  # ... call commands ...
  # .....................
  # reset dotglob, nullglob to their previous values
  [[ $is_nullglob ]] && shopt -s nullglob
  [[ ! $is_dotglob ]] && shopt -u dotglob
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.