ग्लोब पैटर्न के साथ सीपी छिपी हुई फाइलें


13

परिस्थिति :

$ mkdir foo && touch foo/.test
$ cp foo/* .
zsh: no matches found: foo/*
(or bash : cp: cannot stat foo/*’: No such file or directory)

मेरे पास छिपी हुई फ़ोल्डर और फ़ाइलों से भरा एक निर्देशिका है। क्या हो रहा है और इसका हल क्या है?


dotglobको zshglobdots द्वारा अनुवादित किया जाता है जो कि बैश के लिए अमान्य विकल्प नाम है ।

जवाबों:


19

डिस्क्लेमर: यह उत्तर विशेष रूप से बैश से संबंधित है, लेकिन यह बहुत ग्लोब पैटर्न के बारे में सवाल पर लागू होता है!

स्टार चरित्र ( *) एक वाइल्डकार्ड है। वर्णों का एक निश्चित समूह है कि यह जगह लेगा और पहला वर्ण एक बिंदु ( .) है उनमें से एक नहीं है। यह एक विशेष मामला है क्योंकि यूनिक्स फाइल सिस्टम कैसे काम करता है, एक डॉट के साथ शुरू होने वाली फाइलों को "छिपा हुआ" माना जाता है। यही कारण है कि इस तरह के रूप उपकरण है कि इसका मतलब है cp, lsआदि नहीं उन्हें "देख" होगा जब तक कि स्पष्ट रूप से ऐसा करने के लिए कहा था।

उदाहरण

पहले कुछ नमूना डेटा बनाते हैं।

$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}

तो अब हमारे पास निम्नलिखित हैं:

$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3

अब कुछ खेल खेलते हैं। आप कमांड echoका उपयोग यह बताने के लिए कर सकते हैं कि एक विशेष वाइल्डकार्ड क्या है ( *) इस तरह दिए गए कमांड के लिए होगा:

$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3


$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2

$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .dotdir*
.dotdir1 .dotdir2

व्यवहार बदलना?

आप कमांड shopt -s dotglobका उपयोग करने के लिए व्यवहार को बदल सकते हैं *ताकि फाइलों के अलावा regfile1यह भी मेल खाएगा .dotfile1

bashमैन पेज से अंश

dotglob If set, bash includes filenames beginning with a `.' in the results 
        of pathname expansion.

उदाहरण:

$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

आप इस आदेश के साथ इस व्यवहार को वापस कर सकते हैं:

$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3

आपकी स्थिति?

आपके लिए आप बता रहे हैं cpकि आप उन सभी फाइलों को कॉपी करना चाहते हैं जो पैटर्न से मेल खाती हैं *, और कोई भी फाइल नहीं है।

$ cp foo/.* .

या आप यह कर सकते हैं यदि आप fooफ़ोल्डर में सब कुछ चाहते हैं :

$ cp foo .

या आप स्पष्ट हो सकते हैं:

$ cp foot/.* foo/* .

ब्रेस विस्तार का उपयोग करके एक अधिक कॉम्पैक्ट रूप bash:

$ cp foo/{.,}* .

किसी भी समय आप echoअपने प्रस्तावित फ़ाइल पैटर्न को देखने के लिए ट्रिक का उपयोग कर सकते हैं (यह स्टार के लिए फैंसी शब्द है)।

$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3

संयोग से यदि आप फ़ाइलों की निर्देशिका + अन्य निर्देशिकाओं की प्रतिलिपि बनाने जा रहे हैं, तो आप आमतौर पर इसे पुनरावर्ती रूप से करना चाहते हैं, यह -Rस्विच है cp:

$ cp -R foo/. .

1
आप के उपयोग का उल्लेख करना चाहते हैं shopt -s dotglob, echo *तो देता है:.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
Drav Sloan

@DravSloan - सुझाव के लिए धन्यवाद। इसे जोड़ा।
slm

cp -r foo .के बाद से आम तौर पर काम नहीं करेगा cpकॉपी करने के लिए मना कर देगा fooपर ही, तो आप शायद मतलब cp -R foo/. .। (ध्यान दें कि cp -Rमानक एक है)।
स्टीफन चेजलस 15

1
यह भी ध्यान दें कि (काफी समझदारी से), और के विस्तार में zshशामिल नहीं है । में , अगर एक पैटर्न से मेल नहीं खाता, आदेश निरस्त किया गया है (काफी समझदारी से फिर से), इसलिए सामान्य मामले में, हो, तो कोई छिपा या कोई गैर छिपा फ़ाइलों असफल हो जायेगी। ....*zshcp foo/{,.}* .
स्टीफन चेज़लस 15

7
यह उत्तर केवल बैश पर लागू होता है। प्रश्नकर्ता zsh का उपयोग कर रहा है, जहां उत्तर बहुत सरल है और shoptमौजूद नहीं है।
गिल्स एसओ- बुराई को रोकें '

31

के साथ zsh, विशिष्ट तरीका यह है कि D ग्लोब क्वालिफायर ([डी] ओटी फाइलों को शामिल करने के लिए) का उपयोग किया जाए:

cp foo/*(D) .

ध्यान दें कि के साथ या बिना D, zsh globs शामिल कभी नहीं .है और न ही ..(जैसा कि आप उम्मीद थी)।


4

शेल उन फ़ाइलों को छिपा हुआ मान रहा है जब वह *वर्ण को हल करता है , इसलिए cpइनमें से कोई भी फ़ाइल नाम तर्क के रूप में प्राप्त नहीं करता है।

आप उन्हें स्पष्ट रूप से निर्दिष्ट करके कॉपी कर सकते हैं cp foo/.* .


1

यदि आप जो करना चाहते हैं वह सभी फाइलों और निर्देशिकाओं को एक स्थान से दूसरे स्थान पर कॉपी करना है, तो आप मानक rsyncकमांड का उपयोग कर सकते हैं । ऊपर दिए गए उदाहरण में:

mkdir foo && touch foo/.test
rsync -a foo/ .

fooवर्तमान निर्देशिका में छिपी हुई फ़ाइलों और छिपी निर्देशिकाओं सहित, की सभी सामग्रियों की पुनरावृत्ति करेगा । के अंत में अनुगामी स्लैश foo/rsync के लिए महत्वपूर्ण है; इसके साथ केवल सामग्री की fooनकल की जाती है, इसके बिना rsync की भी नकल होगी foo। उदाहरण के लिए:-

mkdir src && mkdir dest && touch src/.test
rsync -a src  dest    // copies 'src' contents to 'dest/src'
rsync -a src/ dest    // copies 'src' contents to 'dest' 

मशीनों के बीच नकल सहित कई अन्य विकल्प उपलब्ध हैं।


1

स्टीफन चेज़लस का ज़श का उत्तर इसमें एक ग्लोब के साथ एकल अभिव्यक्ति के लिए सही है। हालाँकि, यदि आप इसे डिफ़ॉल्ट रूप से सभी अभिव्यक्तियों के लिए सेट करना चाहते हैं, तो आप उपयोग कर सकते हैं

setopt GLOB_DOTS

~/.zshrcइसे स्थायी बनाने के लिए इसे अपने अंदर रखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.