गैर-ASCII या फ़ाइल नाम में गैर-मुद्रण योग्य वर्णों के साथ फ़ाइलों की पहचान करें


24

लगभग 700,000 फ़ाइलों के साथ एक निर्देशिका आकार 80GB में, फ़ाइल नाम में गैर-अंग्रेजी वर्णों के साथ कुछ फ़ाइल नाम हैं। श्रम सूची में फ़ाइल सूची से गुजरने के अलावा अन्य है:

  • इन फ़ाइल नामों को सूचीबद्ध करने या अन्यथा पहचानने का एक आसान तरीका?
  • प्रिंट करने योग्य गैर-अंग्रेज़ी भाषा वर्ण उत्पन्न करने का एक तरीका - वे वर्ण जिन्हें मुद्रण योग्य श्रेणी में सूचीबद्ध नहीं किया गया है man ascii(इसलिए मैं परीक्षण कर सकता हूं कि इन फ़ाइलों की पहचान की जा रही है)?

जवाबों:


32

यह मानते हुए कि "विदेशी" का अर्थ "एएससीआईआई चरित्र नहीं" है, तो आप उन findसभी फाइलों को खोजने के लिए एक पैटर्न के साथ उपयोग कर सकते हैं जिनके नाम में मुद्रण योग्य एएससीआईआई अक्षर नहीं हैं:

LC_ALL=C find . -name '*[! -~]*'

(अंतरिक्ष पहले प्रिंट करने योग्य पर सूचीबद्ध चरित्र है http://www.asciitable.com/ , ~पिछले है।)

संकेत LC_ALL=Cकी आवश्यकता है (वास्तव में, LC_CTYPE=Cऔर LC_COLLATE=C), अन्यथा चरित्र श्रेणी की गलत व्याख्या की जाती है। मैनुअल पेज भी देखें glob(7)। चूंकि ASCII के रूप में तारों की व्याख्या करने का LC_ALL=Cकारण findहै, इसलिए यह πप्रश्न चिह्न के रूप में बहु-बाइट वर्ण (जैसे ) मुद्रित करेगा । इसे ठीक करने के लिए, कुछ प्रोग्राम (जैसे cat) पर पाइप करें या फ़ाइल पर रीडायरेक्ट करें।

वर्ण श्रेणियों को निर्दिष्ट करने के बजाय, [:print:]"मुद्रण योग्य वर्ण" का चयन करने के लिए भी उपयोग किया जा सकता है। सी लोकेल को सेट करना सुनिश्चित करें या आप काफी (प्रतीत होता है) मनमाना व्यवहार करें।

उदाहरण:

$ touch $(printf '\u03c0') "$(printf 'x\ty')"
$ ls -F
dir/  foo  foo.c  xrestop-0.4/  xrestop-0.4.tar.gz  π
$ find -name '*[! -~]*'       # this is broken (LC_COLLATE=en_US.UTF-8)
./x?y
./dir
./π
... (a lot more)
./foo.c
$ LC_ALL=C find . -name '*[! -~]*'
./x?y
./??
$ LC_ALL=C find . -name '*[! -~]*' | cat
./x y
./π
$ LC_ALL=C find . -name '*[![:print:]]*' | cat
./x y
./π

1
ध्यान रखें कि आपके पास ऐसे फ़ाइल नाम हैं जो विदेशी वर्ण सेट का उपयोग कर रहे हैं जो UTF-8 या ASCII के साथ असंगत हैं। उन मामलों में, आप वर्णों के बजाय प्रश्न चिह्न देख सकते हैं।
लेकेन्स्टाइन

1
+1, लेकिन मैं LC_ALL=Cइसके बजाय का उपयोग करेगा LC_COLLATE=Cक्योंकि यह बिना सेटिंग के LC_COLLATE को सेट करने के लिए बहुत मायने नहीं रखता है LC_CTYPEऔर यह सुनिश्चित करने के लिए कि यह अभी भी काम करता है जब LC_ALL चर वातावरण में है।
स्टीफन चेज़लस

अगर SPCहै प्रिंट करने योग्य , तो क्या के बारे में TABऔर LFभी आम तौर पर पाठ फ़ाइलों में पाए जाते हैं?
स्टीफन चेजलस

1
धन्यवाद - इसमें छह फाइलें मिलीं, जिसमें लंबी हाइफ़न, छोटी हाइफ़न और एक बोली का एक संस्करण था। ये सभी एमएस वर्ड से उत्पन्न हुए थे। LC_ALL और LC_COLLATE के बीच सूचीबद्ध फ़ाइलों में कोई अंतर नहीं है। LC_COLLATE ने गैर-ASCII वर्णों को सही ढंग से प्रदर्शित किया जबकि LC_ALL प्रदर्शित ??? बजाय। बहुत बढ़िया जवाब!
संदिग्ध

1
@suspectus I ने स्टीफन के सुझावों के आधार पर उत्तर द्वारा अद्यतन किया। के लिए LC_COLLATEऔर LC_CTYPE, यह भी देखें find(1)मैनपेज।
लेकेनस्टाइन

6

यदि आप प्रत्येक फ़ाइल नाम का उपयोग करके अनुवाद करते हैं tr -d '[\200-\377]'और इसे मूल नाम से तुलना करते हैं, तो किसी भी फ़ाइल नाम के पास विशेष वर्ण नहीं होंगे।

(ऊपर यह मानकर कि आप विदेशी के साथ गैर-एएससीआईआई का मतलब है)


2
वह भी हटा देता है [और ]अधिकांश trकार्यान्वयन में।
स्टीफन चेज़लस

हां - यह हटा दिया [और ]मेरे सिस्टम पर।
सस्पेंस

+1 - समाधान गैर ASCII प्रतीकों के साथ सभी (छह) फ़ाइल नाम मिला (के अलावा [और ]रों)। धन्यवाद।
सस्पेंस

3

आप trकिसी भी विदेशी चरित्र को फ़ाइल नाम से हटाने के लिए उपयोग कर सकते हैं और मूल फ़ाइल नाम के साथ परिणाम की तुलना करके यह देख सकते हैं कि उसमें विदेशी अक्षर हैं या नहीं।

find . -type f > filenames
while read filename; do
      stripped="$(printf '%s\n' "$filename" | tr -d -C '[[:alnum:]][[:space:]][[:punct:]]')"
      test "$filename" = "$stripped" || printf '%s\n' "$filename"; 
done < filenames

4
यह मेरे उत्तर के लिए एक अच्छा विस्तार है, लेकिन यह बहुत सरल है, फ़ाइल नाम उन में newlines हो सकते हैं और फिर आपकी स्क्रिप्ट काम नहीं करेगी
तिमो

1
यदि आप findआउटपुट को पोस्ट-प्रोसेस करना चाहते हैं , तो इस उत्तर में दिखाए गए अनुसार एनयूएल-टर्मिनेटेड आउटपुट / इनपुट का उपयोग करें
लेकेनस्टाइन

0

स्वीकृत उत्तर सहायक है, लेकिन यदि आपके फ़ाइलनाम पहले से ही एन्कोडिंग में निर्दिष्ट हैं LANG/ LC_CTYPE, तो यह बेहतर है:

LC_COLLATE=C find . -name '*[! -~]*'

चरित्र वर्ग इससे प्रभावित होते हैं LC_CTYPE, लेकिन उपरोक्त आदेश केवल वर्ण श्रेणियों का उपयोग नहीं करते हैं, इसलिए LC_CTYPEकेवल असामान्य वर्णों को प्रश्नवाचक चिह्न से प्रतिस्थापित करने से रोकता है।

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