डुप्लिकेट फ़ाइल-नामों की केस-असंवेदनशील खोज


17

मैं डुप्लिकेट फ़ाइल नाम के साथ एक निर्देशिका में सभी फ़ाइलों को खोजने का एक तरीका है, चाहे आवरण (ऊपरी मामले और / या निचले मामले)?

जवाबों:


14

यदि आपके पास GNU उपयोगिताओं (या कम से कम एक सेट जो शून्य-समाप्त लाइनों से निपट सकता है) उपलब्ध है, तो एक अन्य उत्तर में एक महान सेवा है:

find . -maxdepth 1 -print0 | sort -z | uniq -diz

नोट: आउटपुट में शून्य-समाप्त स्ट्रिंग्स होंगे; उपकरण जिसे आप आगे की प्रक्रिया के लिए उपयोग करते हैं, उसे संभालना चाहिए।

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

#!/bin/sh
for f in *; do
  find . -maxdepth 1 -iname ./"$f" -exec echo \; | wc -l | while read count; do
    [ $count -gt 1 ] && echo $f
  done
done

ये क्या पागलपन हे? इस उत्तर को उन तकनीकों की व्याख्या के लिए देखें जो पागल फाइलनाम के लिए इसे सुरक्षित बनाती हैं।


1
मैं बस एक समान पोस्ट करने जा रहा था ... लेकिन इससे भी बदतर जवाब :)
rozcietrzewiacz

2
क्या आपको वास्तव में आवश्यकता है -mindepth?
rozcietrzewiacz

मैं सोलारिस का उपयोग कर रहा हूं। क्या आप हमारे बारे में बात कर रहे हैं? मैंने इसका उपयोग करने की कोशिश की और मुझे कई त्रुटियां दीं।
लामक्रो

@lamcro नहीं, Solaris GNU का उपयोग नहीं करता है find; मैंने गैर-जीएनयू समाधान को शामिल करने के लिए उत्तर को संपादित किया है।
शॉन जे। गोफ

ठीक है। क्या मैं इसे एक पाठ फ़ाइल में पेस्ट कर सकता हूं और इसे निष्पादन अधिकार दे सकता हूं?
लैमक्रो

12

ऊपर कई जटिल जवाब हैं, यह उन सभी की तुलना में सरल और तेज लगता है:

find . -maxdepth 1 | sort -f | uniq -di

यदि आप उपनिर्देशिकाओं में डुप्लिकेट फ़ाइल नाम ढूंढना चाहते हैं, तो आपको केवल फ़ाइल नाम की तुलना करने की आवश्यकता है, न कि संपूर्ण पथ:

find . -maxdepth 2 -printf "%f\n" | sort -f | uniq -di

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

find . -maxdepth 1 -print0 | sort -fz | uniq -diz

-print0(खोज के लिए) और -zविकल्प जिसके कारण ये NUL-समाप्त तारों पर काम करने के लिए (प्रकार और uniq के लिए), के बजाय न्यू लाइन समाप्त तार। चूँकि फ़ाइल नाम में NUL नहीं हो सकता है, यह सभी फ़ाइल नामों के लिए काम करता है।


1
लेकिन शॉन जे। गोफ के जवाब पर मेरी टिप्पणी देखें, आप -प्रिंट0 विकल्प को खोजने के लिए जोड़ सकते हैं, और -ज़ विकल्प को यूनीक और सॉर्ट कर सकते हैं। इसके अलावा, आप के रूप में अच्छी तरह से चाहते हैं। तब यह काम करता है। (मैं संपादित करने के लिए जा रहा हूँ इस आपका जवाब में, यदि आप स्वीकार नहीं करते वापस लौटने के लिए स्वतंत्र लग रहा है)
derobert

अंतिम आदेश मुझे गाड़ी के रिटर्न के बिना आउटपुट दे रहा है (परिणाम सभी एक पंक्ति में है)। मैं कमांड चलाने के लिए Red Hat Linux का उपयोग कर रहा हूँ। पहली कमांड लाइन मेरे लिए सबसे अच्छा काम करती है।
सूर्य अस्त

2

केस-असंवेदनशील तरीके से फ़ाइल नामों की सूची को क्रमबद्ध करें और डुप्लिकेट प्रिंट करें। sortकेस-असंवेदनशील छँटाई के लिए एक विकल्प है। तो जीएनयू uniq, लेकिन अन्य कार्यान्वयन नहीं है, और आप जो कुछ भी कर सकते हैं uniqवह हर तत्व को डुप्लिकेट के एक सेट में प्रिंट करता है, पहले को छोड़कर। GNU टूल के साथ, यह मानते हुए कि किसी फ़ाइल नाम में कोई नई पंक्ति नहीं है, सभी तत्वों को प्रिंट करने का एक आसान तरीका है लेकिन डुप्लिकेट के प्रत्येक सेट में एक:

for x in *; do printf "%s\n" "$x"; done |
sort -f |
uniq -id

विशेष रूप से, डुप्लिकेट के प्रत्येक सेट में सभी तत्वों को मुद्रित करने के लिए, यह मानते हुए कि कोई फ़ाइल नाम में एक नई पंक्ति नहीं है:

for x in *; do printf "%s\n" "$x"; done |
sort -f |
awk '
    tolower($0) == tolower(prev) {
        print prev;
        while (tolower($0) == tolower(prev)) {print; getline}
    }
    1 { prev = $0 }'

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

perl -e '
    foreach (glob("*")) {push @{$f{lc($_)}}, $_}
    foreach (keys %f) {@names = @{$f{$_}}; if (@names > 1) {print "$_\n" foreach @names}}
'

यहाँ एक शुद्ध zsh समाधान है। यह थोड़ी क्रिया है, क्योंकि डुप्लिकेट तत्वों को किसी सरणी या ग्लोब परिणाम में रखने का कोई अंतर्निहित तरीका नहीं है।

a=(*)(N); a=("${(@io)a}")
[[ $#a -le 1 ]] ||
for i in {2..$#a}; do
  if [[ ${(L)a[$i]} == ${(L)a[$((i-1))]} ]]; then
    [[ ${(L)a[$i-2]} == ${(L)a[$((i-1))]} ]] || print -r $a[$((i-1))]
    print -r $a[$i]
  fi
done

1

GNU के बिना find:

LANG=en_US ls | tr '[A-Z]' '[a-z]' | uniq -c | awk '$1 >= 2 {print $2}'


2
trहै बहुत किसी भी वर्ण सेट जो चरित्र प्रति एक एकल बाइट की तुलना में अधिक का उपयोग करता है पर कहर बरपा की संभावना है। उपयोग करते समय केवल UTF-8 के पहले 256 अक्षर सुरक्षित हैं tr। से विकिपीडिया टीआर (यूनिक्स) .. के अधिकांश संस्करणों trजीएनयू सहित, trऔर क्लासिक यूनिक्स tr, एकल बाइट्स पर काम करते हैं और यूनिकोड अनुरूप नहीं हैं ..
Peter.O

1
मेरी पिछली टिप्पणी के लिए अपडेट करें .. केवल UTF-8 के पहले 128 अक्षर सुरक्षित हैं। अध्यादेश श्रेणी 0..127 से ऊपर के सभी UTF-8 वर्ण सभी बहु-बाइट हैं और अन्य वर्णों में अलग-अलग बाइट मान हो सकते हैं। केवल 0..127 की सीमा में बाइट्स में एक से एक अद्वितीय चरित्र का जुड़ाव होता है।
पीटर।

प्लस uniqमें एक केस-असंवेदनशील झंडा है i।
जेमी किट्सन

1

मैंने अंत में इसे इस तरह से प्रबंधित किया:

find . | tr '[:upper:]' '[:lower:]' | sort | uniq -d

मैंने findइसके बजाय इसका उपयोग किया lsक्योंकि मुझे पूर्ण पथ (बहुत सारे उपनिर्देशिका) की आवश्यकता थी। मुझे नहीं लगा कि मैं यह कैसे कर सकता हूं ls


2
दोनों sortऔर uniqक्रमशः फ्लैग-केस फ्लैग, एफ और आई हैं।
जेमी किट्सन

-1

किसी और के लिए जो फिर से नाम बदलना चाहता है आदि में से एक फाइल:

find . -maxdepth 1 | sort -f | uniq -di | while read f; do echo mv "$f" "${f/.txt/_.txt}"; done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.