समस्या क्या है
सबसे पहले, कई उपयोगिताओं के लिए, आपके पास फ़ाइल नाम के साथ शुरू होने वाला मुद्दा होगा -। जब में:
sh -c 'inline sh script here' other args
अन्य आर्गों को पारित किया जाता है inline sh script; perlसमकक्ष के साथ ,
perl -e 'inline perl script here' other args
अन्य आर्ग और अधिक विकल्प के लिए के लिए स्कैन किए पर्ल पहले, इनलाइन स्क्रिप्ट के लिए नहीं। उदाहरण के लिए, यदि -eBEGIN{do something evil}वर्तमान निर्देशिका में एक फ़ाइल है ,
perl -ne 'inline perl script here;' *
(साथ या बिना -n) कुछ बुराई करेगा।
अन्य उपयोगिताओं की तरह, इसके लिए चारों ओर का काम अंत-विकल्प मार्कर ( --) का उपयोग करना है:
perl -ne 'inline perl script here;' -- *
लेकिन फिर भी, यह अभी भी खतरनाक है और इसके <>द्वारा उपयोग किए गए ऑपरेटर के लिए नीचे है -n/ -p।
मुद्दे को perldoc perlopप्रलेखन में समझाया गया है।
उस विशेष ऑपरेटर का उपयोग इनपुट की एक पंक्ति (एक रिकॉर्ड, रिकॉर्ड डिफ़ॉल्ट रूप से रेखाएं) को पढ़ने के लिए किया जाता है, जहां वह इनपुट बारी-बारी से पारित किए गए प्रत्येक तर्क से आ रहा है @ARGV।
में:
perl -pe '' a b
-pwhile (<>)कोड (यहां खाली) के चारों ओर एक लूप का अर्थ है ।
<>पहली बार खुलेगा a, एक समय में एक लाइन रिकॉर्ड करें जब तक कि फ़ाइल समाप्त न हो जाए और फिर खुले b...
समस्या यह है कि, फ़ाइल को खोलने के लिए, यह पहले, असुरक्षित रूप का उपयोग करता है open:
open ARGV, "the file as provided"
उस रूप के साथ, यदि तर्क है
"> afile", यह afileलेखन मोड में खुलता है,
"cmd|", यह चलता है cmdऔर इसे आउटपुट पढ़ता है।
"|cmd", आप इनपुट के लिए लिखने के लिए एक धारा खुला है cmd।
उदाहरण के लिए:
perl -pe '' 'uname|'
नामक फ़ाइल की सामग्री का उत्पादन नहीं करता है uname|(पूरी तरह से मान्य फ़ाइल नाम btw), लेकिन unameकमांड का आउटपुट ।
यदि आप चला रहे हैं:
perl -ne 'something' -- *
और किसी ने rm -rf "$HOME"|वर्तमान निर्देशिका में (फिर एक पूरी तरह से वैध फ़ाइल नाम) नामक एक फ़ाइल बनाई है (उदाहरण के लिए क्योंकि वह निर्देशिका एक बार दूसरों द्वारा लिखी गई थी, या आपने एक डॉगी संग्रह निकाला है, या आपने कुछ डॉगी कमांड चलाया है, या किसी अन्य सॉफ्टवेयर में एक और भेद्यता का शोषण किया गया था), तो आप बड़ी मुसीबत में हैं। जिन क्षेत्रों में इस समस्या से अवगत होना महत्वपूर्ण है, वे सार्वजनिक क्षेत्रों में स्वचालित रूप से टूल प्रोसेसिंग फाइल हैं /tmp(या ऐसे उपकरण जिन्हें टूल कहा जा सकता है)।
फ़ाइलें बुलाया > foo, foo|, |fooएक समस्या है। लेकिन कुछ हद तक < fooऔर fooASCII रिक्ति वर्ण (अंतरिक्ष, टैब, newline, cr ...) के साथ-साथ उन फ़ाइलों को संसाधित नहीं किया जाएगा या गलत एक हो जाएगा।
यह भी सावधान रहें कि कुछ मल्टी-बाइट कैरेक्टर सेट (जैसे ǖBIG5-HKSCS) में कुछ अक्षर बाइट 0x7c के एन्कोडिंग में समाप्त होते हैं |।
$ printf ǖ | iconv -t BIG5-HKSCS | od -tx1 -tc
0000000 88 7c
210 |
0000002
तो उस चारसेट का उपयोग करने वाले स्थानों में,
perl -pe '' ./nǖ
उपयोगकर्ता के स्थान में उस फ़ाइल नाम की व्याख्या करने की कोशिश नहीं करेगा ./n\x88जैसा कि कमांड को चलाने की कोशिश perlकरेगा !
कैसे ठीक करें / आसपास काम करें
AFAIK, ऐसा कुछ भी नहीं है जिसे आप perlएक बार और सभी सिस्टम-वाइड के असुरक्षित डिफ़ॉल्ट व्यवहार को बदलने के लिए कर सकते हैं ।
सबसे पहले, समस्या केवल फ़ाइल नाम के प्रारंभ और अंत में वर्णों के साथ होती है। तो, जबकि perl -ne '' *या perl -ne '' *.txtएक समस्या है,
perl -ne 'some code' ./*.txt
क्योंकि सभी तर्कों अब के साथ शुरू नहीं कर रहा है ./और में अंत .txt(ऐसा नहीं -, <, >, |, अंतरिक्ष ...)। अधिक आम तौर पर, ग्लब्स के साथ उपसर्ग करना एक अच्छा विचार है ./। यह भी बुलाया फ़ाइलों के साथ समस्याओं से बचा जाता है -या -कई अन्य उपयोगिताओं के साथ शुरू होता है (और यहां, इसका मतलब है कि आपको अंत-विकल्प ( --) मार्कर की आवश्यकता नहीं है)।
मोड -Tचालू करने के लिए उपयोग करने taintसे कुछ हद तक मदद मिलती है। यह दुर्भावनापूर्ण फ़ाइल (केवल >और |मामलों, नहीं <या व्हॉट्सएप के लिए) का सामना होने पर कमांड को रद्द कर देगा ।
इस तरह के आदेशों का उपयोग करते समय यह उपयोगी होता है क्योंकि यह आपको सचेत करता है कि कुछ गड़बड़ चल रहा है। हालांकि, कुछ स्वचालित प्रसंस्करण करते समय यह वांछनीय नहीं हो सकता है, क्योंकि इसका मतलब है कि कोई व्यक्ति केवल फ़ाइल बनाकर उस प्रसंस्करण को विफल कर सकता है ।
आप हर फ़ाइल पर कार्रवाई करने, उनके नाम की परवाह किए बिना चाहते हैं, तो आप उपयोग कर सकते हैं CPAN पर मॉड्यूल (दुर्भाग्य से आमतौर पर डिफ़ॉल्ट रूप से स्थापित नहीं)। यह एक बहुत छोटा मॉड्यूल है जो करता है:ARGV::readonly perl
sub import{
# Tom Christiansen in Message-ID: <24692.1217339882@chthon>
# reccomends essentially the following:
for (@ARGV){
s/^(\s+)/.\/$1/; # leading whitespace preserved
s/^/< /; # force open for input
$_.=qq/\0/; # trailing whitespace preserved & pipes forbidden
};
};
मूल रूप से, यह @ARGV " foo|"को उदाहरण के लिए बदलकर सुरक्षित करता है "< ./ foo|\0"।
आप BEGINअपने perl -n/-pआदेश में एक बयान में ऐसा कर सकते हैं :
perl -pe 'BEGIN{$_.="\0" for @ARGV} your code here' ./*
यहां हम इसे उस धारणा पर सरल करते हैं ./जिसका उपयोग किया जा रहा है।
कि (और का एक पक्ष प्रभाव ARGV::readonly), हालांकि वह यह है कि $ARGVमें your code hereपता चलता है कि NUL चरित्र अनुगामी।
अद्यतन 2015-06-03
perlv5.21.5 और इसके बाद के संस्करण में एक नया <<>>ऑपरेटर होता है जो इस तरह के व्यवहार करता है <>सिवाय इसके कि यह उस विशेष प्रसंस्करण को नहीं करेगा । तर्क केवल फ़ाइल नाम के रूप में माना जाएगा। तो उन संस्करणों के साथ, अब आप लिख सकते हैं:
perl -e 'while(<<>>){ ...;}' -- *
(यह मत भूलना --या उपयोग न करें ./*) इसके डर के बिना फाइलों पर ओवरराइटिंग या अप्रत्याशित कमांड चलाना।
-n/ फिर -pभी खतरनाक <>रूप का उपयोग करते हैं । और सावधान रहना सहानुभूति अभी भी पीछा किया जा रहा है, ताकि जरूरी नहीं है कि यह अविश्वसनीय निर्देशिकाओं में उपयोग करने के लिए सुरक्षित है।