अन्य उत्तरों ने इस प्रश्न के दो प्रमुख पहलुओं में से एक को संबोधित किया है: कि आपके द्वारा आवश्यक नाम बदलने के संचालन को सफलतापूर्वक कैसे पूरा किया जाए। इस उत्तर का उद्देश्य यह बताना है कि rename
कमांड के संदर्भ में उस अजीब "नंगेपन की अनुमति नहीं है" त्रुटि संदेश सहित आपके कमांड ने काम क्यों नहीं किया ।
इस उत्तर का पहला खंड rename
और पर्ल के बीच के संबंध के बारे में है और rename
आप इसे पारित करने वाले पहले कमांड-लाइन तर्क का उपयोग कैसे करते हैं, जो कि इसका कोड तर्क है। दूसरा खंड इस बारे में है कि शेल कैसे विस्तार करता है - विशेष रूप से ग्लोबिंग - एक तर्क सूची बनाने के लिए। तीसरा खंड पर्ल कोड में चल रहा है जो "बेयरवर्ड को अनुमति नहीं" त्रुटियों को देता है। अंत में, चौथा खंड उन सभी चरणों का सारांश है जो कमांड में प्रवेश करने और त्रुटि प्राप्त करने के बीच होता है।
1. जब rename
आप अजीब त्रुटि संदेश देते हैं, तो अपनी खोज में "पर्ल" जोड़ें।
डेबियन और उबंटू में, rename
कमांड एक पर्ल स्क्रिप्ट है जो फ़ाइल का नामकरण करती है। 14.04 एलटीएस सहित पुराने रिलीज पर - जो अभी भी इस लेखन के रूप में समर्थित है - यह कमांड के लिए ( अप्रत्यक्ष रूप से ) इंगित करने वाला एक प्रतीकात्मक लिंक था । नए रिलीज पर, यह नए कमांड के बजाय इंगित करता है । उन दो पर्ल नाम बदलना ज्यादातर उसी तरह से काम करते हैं, और मैं इस उत्तर के बाकी हिस्सों के लिए उन दोनों को संदर्भित करूंगा ।prename
file-rename
rename
जब आप rename
कमांड का उपयोग करते हैं , तो आप सिर्फ पर्ल कोड नहीं चला रहे हैं जो किसी और ने लिखा है। आप अपना स्वयं का पर्ल कोड भी लिख रहे हैं और rename
इसे चलाने के लिए कह रहे हैं। इसका कारण यह है कि पहली कमांड-लाइन तर्क जो आप rename
कमांड में पास करते हैं , विकल्प तर्कों के अलावा -n
, वास्तविक पर्ल कोड के होते हैं । rename
आदेश में से प्रत्येक पर संचालित करने के लिए इस कोड का उपयोग करता है pathnames है कि आप बाद में कमांड लाइन तर्क के रूप में यह गुजरती हैं। (यदि आप कोई पाथनाम तर्क नहीं देते हैं, तो मानक इनपुटrename
से , एक प्रति पंक्ति, से पथनाम पढ़ता है ।)
कोड एक लूप के अंदर चलाया जाता है , जो पथनाम के अनुसार एक बार पुनरावृत्त करता है । लूप के प्रत्येक पुनरावृत्ति के शीर्ष पर, आपके कोड के चलने से पहले, विशेष $_
चर को वर्तमान में संसाधित किए जा रहे पथनाम को सौंपा गया है। यदि आपका कोड $_
किसी और चीज़ के मान को बदलने का कारण बनता है, तो नया नाम रखने के लिए उस फ़ाइल का नाम बदल दिया जाता है।
पर्ल में कई अभिव्यक्तियां$_
चर पर निहित होती हैं, जब उन्हें एक ऑपरेंड के रूप में उपयोग करने के लिए कोई अन्य अभिव्यक्ति नहीं दी जाती है । उदाहरण के लिए, प्रतिस्थापन अभिव्यक्ति चर द्वारा आयोजित स्ट्रिंग में $str =~ s/foo/bar/
पहली घटना को बदल देती है , या इसमें शामिल नहीं होने पर इसे अपरिवर्तित छोड़ देती है । तुम सिर्फ लिखते हैं तो स्पष्ट रूप से उपयोग किए बिना ऑपरेटर , तो यह पर चल रही है । यह कहना है कि के लिए कम है ।foo
$str
bar
foo
s/foo/bar/
=~
$_
s/foo/bar/
$_ =~ s/foo/bar/
यह पारित करने के लिए आम है एक s///
अभिव्यक्ति के लिए rename
कोड तर्क (यानी, पहले कमांड लाइन तर्क) के रूप में है, लेकिन आप की जरूरत नहीं है। आप इसे किसी भी पर्ल कोड को दे सकते हैं जिसे आप लूप के अंदर चलाना चाहते हैं, $_
(सशर्त रूप से) इसे संशोधित करने के प्रत्येक मूल्य की जांच करने के लिए ।
इसके बहुत सारे शांत और उपयोगी परिणाम हैं , लेकिन उनमें से अधिकांश इस सवाल और जवाब के दायरे से परे हैं। मुख्य कारण मैं इसे यहां लाता हूं - वास्तव में, मुख्य कारण जो मैंने इस उत्तर को पोस्ट करने का फैसला किया है - यह मुद्दा बनाने के लिए है, क्योंकि पहला तर्क rename
वास्तव में पर्ल कोड है, कभी भी आपको एक अजीब त्रुटि संदेश मिलता है और आप खोज करने से इसके बारे में जानकारी प्राप्त करने में परेशानी होती है, आप खोज स्ट्रिंग में "पर्ल" जोड़ सकते हैं (या "नाम बदलें" "पर्ल" के साथ, कभी-कभी) और आपको अक्सर उत्तर मिल जाएगा।
2. कमान के साथ rename *.DAT *.dat
, rename
कभी नहीं देखा *.DAT
!
की तरह एक आदेश rename s/foo/bar/ *.txt
आम तौर पर पास नहीं *.txt
करने के लिए एक कमांड लाइन तर्क के रूप में rename
कार्यक्रम, और आप इसे नहीं करना चाहती , जब तक आप एक फ़ाइल जिसका नाम का शाब्दिक है *.txt
, जो उम्मीद है कि तुम नहीं।
rename
व्याख्या नहीं करता ग्लोब पैटर्न की तरह *.txt
, *.DAT
, *.dat
, x*
, *y
, या *
जब पथ नाम तर्क के रूप में यह करने के लिए पारित कर दिया। इसके बजाय, आपका शेल उन पर पथनाम विस्तार करता है (जिसे फ़ाइल नाम विस्तार भी कहा जाता है, और ग्लोबिंग भी कहा जाता है)। rename
उपयोगिता चलने से पहले ऐसा होता है। शेल संभावित रूप से कई पथनामों में ग्लब्स का विस्तार करता है और उन सभी को अलग-अलग कमांड-लाइन तर्क के रूप में पास करता है rename
। उबंटू में, आपका इंटरएक्टिव शेल बैश है , जब तक कि आपने इसे नहीं बदला है, यही वजह है कि मैंने ऊपर बैश संदर्भ मैनुअल में लिंक किया है।
एक ऐसी स्थिति है जहां एक ग्लोब पैटर्न को एकल unexpanded कमांड-लाइन तर्क के रूप में पारित किया जा सकता है rename
: जब यह किसी भी फाइल से मेल नहीं खाता है। अलग-अलग गोले इस स्थिति में अलग-अलग डिफ़ॉल्ट व्यवहार प्रदर्शित करते हैं, लेकिन बैश का डिफ़ॉल्ट व्यवहार केवल शब्दशः पास करना है। हालांकि, आप शायद ही कभी ऐसा चाहते हैं! यदि आप इसे चाहते थे, तो आपको यह सुनिश्चित करना चाहिए कि पैटर्न का विस्तार नहीं किया गया है, इसे उद्धृत करके। यह किसी भी आदेश के लिए तर्क पारित करने के लिए जाता है, न कि केवल करने के लिए rename
।
उद्धरण केवल ग्लोबिंग (फ़ाइल नाम विस्तार) के लिए नहीं है, क्योंकि ऐसे अन्य विस्तार हैं जो आपके खोल को बिना पढ़े हुए पाठ पर और उनमें से कुछ के लिए नहीं , बल्कि दूसरों को भी "
"
उद्धरणों में संलग्न पाठ पर करते हैं। सामान्य तौर पर, कभी-कभी आप एक तर्क पारित करना चाहते हैं जिसमें ऐसे अक्षर होते हैं जिन्हें विशेष रूप से शेल द्वारा इलाज किया जा सकता है, जिसमें रिक्त स्थान भी शामिल है, आपको इसे उद्धृत करना चाहिए, अधिमानतः '
'
उद्धरण के साथ ।
पर्ल कोड s/foo/bar/
में शेल द्वारा विशेष रूप से व्यवहार किया गया कुछ भी शामिल नहीं है, लेकिन यह मेरे लिए एक अच्छा विचार होगा कि मैंने भी - और लिखा है 's/foo/bar/'
। (वास्तव में, केवल यही कारण नहीं था कि यह कुछ पाठकों के लिए भ्रामक होगा, क्योंकि मैंने अभी तक उद्धृत करने के बारे में बात नहीं की है।) इसका कारण मैं कहता हूं कि यह अच्छा होगा क्योंकि यह बहुत आम है कि पर्ल कोड शामिल नहीं है। इस तरह के पात्र, और अगर मुझे वह कोड बदलना था, तो शायद मुझे याद नहीं होगा कि क्या उद्धृत करने की आवश्यकता है। इसके विपरीत, यदि आप चाहते हैं कि शेल एक ग्लोब का विस्तार करे, तो इसे उद्धृत नहीं किया जाना चाहिए ।
3. पर्ल दुभाषिया का अर्थ "नंगेपन की अनुमति नहीं है" से है
आपके प्रश्न में दिखाए गए त्रुटि संदेश से पता चलता है कि, जब आप दौड़ते थे rename *.DAT *.dat
, तो आपका खोल *.DAT
एक या एक से अधिक फ़ाइलनामों की सूची में विस्तारित होता था, और उन फ़ाइलनामों में से पहला था b1.DAT
। उसके बाद के सभी तर्कों - दोनों में से किसी का भी विस्तार हुआ *.DAT
और किसी का भी *.dat
उस तर्क के बाद से विस्तार हुआ , इसलिए उनकी व्याख्या पथ प्रदर्शकों के रूप में की गई।
क्योंकि वास्तव में जो चलाया गया वह कुछ ऐसा था rename b1.DAT ...
, और क्योंकि rename
इसके पहले गैर-विकल्प तर्क को पर्ल कोड के रूप में b1.DAT
माना जाता है, सवाल यह बन जाता है: जब आप इसे पर्ल कोड के रूप में चलाते हैं तो इन "नंगेपन की अनुमति नहीं" त्रुटियों का उत्पादन क्यों करता है ?
Bareword "b1" not allowed while "strict subs" in use at (user-supplied code).
Bareword "DAT" not allowed while "strict subs" in use at (user-supplied code).
एक शेल में, हम अपने स्ट्रिंग्स को अनपेक्षित शेल विस्तार से बचाने के लिए उद्धृत करते हैं जो अन्यथा उन्हें अन्य स्ट्रिंग्स में स्वचालित रूप से बदल देगा (ऊपर अनुभाग देखें)। शेल विशेष प्रयोजन प्रोग्रामिंग भाषाएं हैं जो सामान्य-उद्देश्य वाली भाषाओं से बहुत अलग तरीके से काम करती हैं (और उनके बहुत ही अजीब वाक्यविन्यास और शब्दार्थ इसे दर्शाते हैं)। लेकिन पर्ल एक सामान्य-उद्देश्य वाली प्रोग्रामिंग भाषा है और, अधिकांश सामान्य-प्रयोजन प्रोग्रामिंग भाषाओं की तरह, पर्ल में उद्धृत करने का मुख्य उद्देश्य तार की रक्षा करना नहीं है , बल्कि उनका उल्लेख करना है। यह वास्तव में एक तरह से अधिकांश प्रोग्रामिंग भाषाएं प्राकृतिक भाषा के समान हैं। अंग्रेजी में, और मान लीजिए कि आपके पास एक कुत्ता है, "आपका कुत्ता" एक दो-शब्द वाक्यांश है, जबकि आपका कुत्ता एक कुत्ता है। इसी तरह, पर्ल में, '$foo'
एक स्ट्रिंग है, जबकि $foo
कुछ ऐसा है जिसका नाम है $foo
।
हालांकि, हर दूसरे सामान्य-प्रयोजन प्रोग्रामिंग भाषा के विपरीत, पर्ल कभी-कभी एक स्ट्रिंग का उल्लेख करते हुए भी अनछुए पाठ की व्याख्या करेगा - एक स्ट्रिंग जो कि "समान" है, इस अर्थ में कि यह एक ही वर्ण से बना है। वही आदेश। यह केवल उस तरह से कोड की व्याख्या करने का प्रयास करेगा यदि यह एक नंगेपन (कोई या अन्य सतर्क नहीं है , नीचे देखें), और इसके बाद इसे देने के लिए कोई अन्य अर्थ नहीं मिल सकता है। तब तक इसे एक स्ट्रिंग के रूप में लिया जाएगा, जब तक कि आप इसे प्रतिबंधों को सक्षम करने से नहीं बताते हैं ।$
पर्ल में वेरिएबल्स आमतौर पर एक पंक्चुएटिंग चरित्र से शुरू होते हैं , जिसे एक सुपरगिल कहा जाता है , जो व्यापक प्रकार के चर को निर्दिष्ट करता है। उदाहरण के लिए, स्केलर का$
मतलब है , सरणी का मतलब है , और हैश का मतलब है@
%
। ( अन्य लोग भी हैं। ) अगर आपको लगता है कि भ्रमित (या उबाऊ) पाते हैं, तो चिंता न करें, क्योंकि मैं केवल यह कहने के लिए ला रहा हूं कि जब एक वैध नाम पर्ल प्रोग्राम में दिखाई देता है, लेकिन उस नाम से पहले नहीं है कहा जाता है कि यह एक नंगेपन है ।
बेयरवर्ड विभिन्न उद्देश्यों की पूर्ति करते हैं, लेकिन वे आमतौर पर एक अंतर्निहित फ़ंक्शन या उपयोगकर्ता द्वारा परिभाषित सबरूटीन को इंगित करते हैं जो कार्यक्रम में परिभाषित किया गया है (या प्रोग्राम द्वारा उपयोग किए गए मॉड्यूल में)। पर्ल का कोई अंतर्निहित कार्य नहीं है जिसे कहा जाता है b1
या DAT
इसलिए, जब पर्ल इंटरप्रेटर कोड को देखता है b1.DAT
, तो यह इलाज करने की कोशिश करता है b1
और DAT
सबरूटीन के नामों के रूप में। यह मानते हुए कि इस तरह के किसी भी उप-समूह को परिभाषित नहीं किया गया है, यह विफल है। फिर, बशर्ते प्रतिबंध सक्षम नहीं किए गए हैं, यह उन्हें तार के रूप में मानता है। यह काम करेगा, हालांकि आप वास्तव में ऐसा करने का इरादा रखते हैं या नहीं, यह किसी का अनुमान है। पर्ल का .
ऑपरेटर स्ट्रिंग को समेटता है , इसलिए b1.DAT
स्ट्रिंग का मूल्यांकन करता हैb1DAT
। यानी, b1.DAT
कुछ ऐसा लिखने का एक बुरा तरीका है 'b1' . 'DAT'
या "b1" . "DAT"
।
आप कमांड चलाकर खुद इसका परीक्षण कर सकते हैं perl -E 'say b1.DAT'
, जो शॉर्ट पर्ल स्क्रिप्ट say b1.DAT
को पर्ल इंटरप्रेटर तक पहुंचाता है, जो इसे चलाता है, छपाई करता है b1DAT
। (है कि आदेश में, '
'
उद्धरण खोल पारित करने के लिए बता say b1.DAT
अन्यथा, अंतरिक्ष का कारण होता है; एक भी कमांड लाइन तर्क के रूप में say
और b1.DAT
किए जाने की अलग शब्द के रूप में पार्स और perl
उन्हें अलग तर्क के रूप में प्राप्त होगा। perl
करता नहीं , उद्धरण देख खुद को शेल उन्हें हटा देता है ।)
लेकिन अब,use strict;
पहले पर्ल स्क्रिप्ट में लिखने का प्रयास करेंsay
। अब यह उसी प्रकार की त्रुटि के साथ विफल हो जाता है जिसे आप प्राप्त करते हैं rename
:
$ perl -E 'use strict; say b1.DAT'
Bareword "b1" not allowed while "strict subs" in use at -e line 1.
Bareword "DAT" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
ऐसा इसलिए हुआ क्योंकि use strict;
पर्ल इंटरप्रेटर को स्ट्रिंग्स के रूप में नंगे पासवर्ड का इलाज करने से प्रतिबंधित किया गया था। इस विशेष सुविधा को प्रतिबंधित करने के लिए, यह वास्तव में केवल subs
प्रतिबंध को सक्षम करने के लिए पर्याप्त होगा । यह कमांड ऊपर की तरह ही त्रुटियाँ पैदा करती है:
perl -E 'use strict "subs"; say b1.DAT'
लेकिन आमतौर पर पर्ल प्रोग्रामर सिर्फ लिखेंगे use strict;
, जो subs
प्रतिबंध और दो अन्य को सक्षम बनाता है। use strict;
आमतौर पर अभ्यास की सिफारिश की जाती है। तो rename
कमांड आपके कोड के लिए ऐसा करता है । यही कारण है कि आपको वह त्रुटि संदेश मिलता है।
4. संक्षेप में, यही हुआ:
- आपका शेल
b1.DAT
पहले कमांड-लाइन तर्क के रूप में पारित हुआ , जिसने rename
प्रत्येक पाथनाम तर्क के लिए लूप में चलने के लिए पर्ल कोड के रूप में व्यवहार किया।
- यह मतलब लेने के लिए
b1
और ऑपरेटर के DAT
साथ जुड़ा हुआ था .
।
b1
और DAT
सिगल्स के साथ उपसर्ग नहीं किया गया था, इसलिए उन्हें नंगे पासवर्ड के रूप में माना जाता था।
- उन दो नंगे पासवर्ड को बिल्ट-इन फ़ंक्शंस या किसी भी यूज़र-डिफ़ाइंड सबरूटीन्स के नाम के रूप में लिया गया होगा, लेकिन इस तरह के किसी भी नाम में कोई भी चीज़ नहीं थी।
- यदि "सख्त उप" को सक्षम नहीं किया गया था, तो उन्हें स्ट्रिंग अभिव्यक्तियों
'b1'
और 'DAT
'और संक्षिप्त' की तरह माना जाता था। यह आपके इच्छित उद्देश्य से बहुत दूर है, जो बताता है कि यह सुविधा अक्सर मददगार नहीं होती है।
- लेकिन "सख्त बाद के चरणों" सक्षम किया गया था, क्योंकि
rename
सभी के लिए सक्षम बनाता प्रतिबंध ( vars
, refs
, और subs
)। इसलिए, आपको इसके बजाय एक त्रुटि मिली।
rename
इस त्रुटि के कारण छोड़ दिया। चूँकि इस प्रकार की त्रुटि जल्दी हुई, इसलिए कोई फ़ाइल नाम बदलने का प्रयास नहीं किया गया, भले ही आप उत्तीर्ण नहीं हुए थे -n
। यह एक अच्छी बात है, जो अक्सर उपयोगकर्ताओं को अनजाने फ़ाइल नाम परिवर्तन से बचाता है और कभी-कभी वास्तविक डेटा हानि से भी।
धन्यवाद ज़ाना को जाता है , जिन्होंने मुझे इस उत्तर के इलियर ड्राफ्ट में कई महत्वपूर्ण कमियों को दूर करने में मदद की । उसके बिना, इस उत्तर ने रास्ता कम कर दिया होता, और शायद इसे पोस्ट नहीं किया जाता।