मैं एक फ़ोल्डर पदानुक्रम में सभी अलग फ़ाइल एक्सटेंशन कैसे प्राप्त कर सकता हूं?


235

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

शेल से इसे प्राप्त करने का सबसे अच्छा तरीका क्या होगा?

जवाबों:


347

इसे आज़माएँ (निश्चित नहीं कि यह सबसे अच्छा तरीका है, लेकिन यह काम करता है):

find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

यह निम्नलिखित के रूप में काम करता है:

  • वर्तमान फ़ोल्डर से सभी फ़ाइलें खोजें
  • यदि कोई हो तो फाइलों का प्रिंट एक्सटेंशन
  • एक अद्वितीय क्रमबद्ध सूची बनाएं

8
केवल संदर्भ के लिए: यदि आप कुछ निर्देशिकाओं को खोज से बाहर रखना चाहते हैं (उदाहरण के लिए .svn), तो find . -type f -path '*/.svn*' -prune -o -print | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u स्रोत का
डेनिस गोलोमेज़ोव

रिक्त स्थान से कोई अंतर नहीं पड़ेगा। प्रत्येक फ़ाइल का नाम अलग लाइन में होगा, इसलिए फ़ाइल सूची परिसीमन स्थान नहीं होगा "\ n"।
इवान नेवोस्त्रुव

1
विंडोज पर, यह बेहतर काम करता है और खोजने की तुलना में बहुत तेज़ है: dir / s / b | perl -ne 'Print $ 1 यदि m / / सॉर्ट -यू
रयान


8
भिन्नता, यह सूची को प्रति एक्सटेंशन के साथ दिखाती है:find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort | uniq -c | sort -n
marcovtwout

54

पाइप के लिए कोई ज़रूरत नहीं है sort, जाग यह सब कर सकते हैं:

find . -type f | awk -F. '!a[$NF]++{print $NF}'

मुझे यह एक उपनाम के रूप में काम करने के लिए नहीं मिल रहा है, मैं जाग रहा हूं: स्रोत लाइन 1 संदर्भ में वाक्यविन्यास त्रुटि >>> है! [A] <<< awk: स्रोत लाइन पर बाहर निकल रहा है 1. मैं क्या गलत कर रहा हूं? मेरे उर्फ इस तरह परिभाषित किया गया है: उर्फ file_ext = "खोजने के प्रकार च -name। ' | Awk -F'। 'एक [$ एनएफ] ++ {प्रिंट $ एनएफ}!"
user2602152

2
@ user2602152 समस्या यह है कि आप aliasकमांड के लिए पूरे एक-लाइनर को उद्धरण के साथ घेरने की कोशिश कर रहे हैं, लेकिन कमांड स्वयं पहले से ही कमांड को खोजने के लिए उद्धरण का उपयोग करता है। इसे ठीक करने के लिए मैं bashशाब्दिक स्ट्रिंग सिंटैक्स का उपयोग alias file_ext=$'find . -type f -name "*.*" | awk -F. \'!a[$NF]++{print $NF}\''
करूंगा

यह काम नहीं करता है अगर एक उप-व्यक्ति के पास ए। इसमें नाम है और फाइल में फाइल एक्सटेंशन नहीं है। उदाहरण: जब हम मेनडियर से भागेंगे तो यह विफल हो जाएगाmaindir/test.dir/myfile
नेल्सन

1
@NelsonTeixeira -printf "%f\n"'खोज' कमांड के अंत में जोड़ें और अपने परीक्षण को फिर से चलाएँ।
घेराबंदी

41

पुनरावर्ती संस्करण:

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u

यदि आप योग चाहते हैं (विस्तार कितनी बार देखा गया था):

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort | uniq -c | sort -rn

गैर-पुनरावर्ती (एकल फ़ोल्डर):

for f in *.*; do printf "%s\n" "${f##*.}"; done | sort -u

मैं इस मंच पोस्ट पर आधारित है , क्रेडिट वहाँ जाना चाहिए।


महान! मेरे git परिदृश्य के लिए भी काम करता है, यह पता लगाने की कोशिश कर रहा था कि किस प्रकार की फाइलें मैंने आखिरी प्रतिबद्ध में छुआ है:git show --name-only --pretty="" | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
vulcan raven

30

शक्ति कोशिका:

dir -recurse | select-object extension -unique

के लिए धन्यवाद http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html


20
ओपी ने कहा कि "एक लिनक्स मशीन पर"
फोर्ब्समाइस्टर

9
वास्तव में अब linux के लिए अग्रसर है: github.com/Microsoft/PowerShell-DSC-for-Linux
KIC

4
जैसा कि लिखा गया है, यह उन निर्देशिकाओं को भी उठाएगा जिनके पास .उनमें है (जैसे आउटपुट में jquery-1.3.4दिखाएगा .4)। dir -file -recurse | select-object extension -uniqueकेवल फ़ाइल एक्सटेंशन प्राप्त करने के लिए बदलें ।
MCW

1
@Forbesmyester: विंडोज वाले लोगों (मेरे जैसे) को यह सवाल मिलेगा। तो यह उपयोगी है।
रोएल

1
पॉवर्सशेल उत्तर के लिए धन्यवाद। आप यह नहीं मानते कि उपयोगकर्ता कैसे खोजते हैं। बहुत से लोगों ने एक कारण के लिए उत्थान किया
महेश 2

20

मेरा awk-less, sed-less, Perl-less, Python-less POSIX-compliant वैकल्पिक:

find . -type f | rev | cut -d. -f1 | rev  | tr '[:upper:]' '[:lower:]' | sort | uniq --count | sort -rn

चाल यह है कि यह लाइन को उलट देता है और शुरुआत में विस्तार को काट देता है।
यह एक्सटेंशन को लोअर केस में भी परिवर्तित करता है।

उदाहरण आउटपुट:

   3689 jpg
   1036 png
    610 mp4
     90 webm
     90 mkv
     57 mov
     12 avi
     10 txt
      3 zip
      2 ogv
      1 xcf
      1 trashinfo
      1 sh
      1 m4v
      1 jpeg
      1 ini
      1 gqv
      1 gcs
      1 dv

मैक पर, uniqपूरा झंडा नहीं है --count, लेकिन -cठीक काम करता है
worc

12

हर बिंदु को एक बिंदु के साथ खोजें और केवल प्रत्यय दिखाएं।

find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u

यदि आप जानते हैं कि सभी प्रत्यय में 3 वर्ण हैं

find . -type f -name "*.???" | awk -F. '{print $NF}' | sort -u

या सेड के साथ एक से चार वर्णों के साथ सभी प्रत्यय दिखाई देते हैं। प्रत्यय में आप जिन वर्णों की अपेक्षा कर रहे हैं, उन्हें {1,4} बदलें।

find . -type f | sed -n 's/.*\.\(.\{1,4\}\)$/\1/p'| sort -u

1
पाइप को 'सॉर्ट' करने की कोई आवश्यकता नहीं है, awk यह सब कर सकता है: खोजें। -Type f -name " " | awk -F '[a [$ NF] ++ {प्रिंट $ NF}'
घेराबंदी

@SiegeX तुम्हारा एक अलग जवाब होना चाहिए। यह पाया गया कि बड़े फ़ोल्डरों के लिए सबसे अच्छा काम करने के लिए कमांड, क्योंकि यह एक्सटेंशन को प्रिंट करता है क्योंकि यह उन्हें ढूंढता है। लेकिन ध्यान दें कि यह होना चाहिए: -नेमी " "
राल्फ

@ राल्फ किया, यहां जवाब पोस्ट किया । इस -name "."बात से बिल्कुल निश्चित नहीं है कि आप किस चीज से मतलब रखते हैं क्योंकि यह पहले से ही है
सेजएक्स

मेरा मतलब था कि इसे "*। *" होना चाहिए, लेकिन StackOverflow * के पात्रों को हटा देता है, जो संभवतः आपकी टिप्पणी में भी हुआ था।
राल्फ

ऐसा लगता है कि यह स्वीकृत उत्तर होना चाहिए, awk एक कमांड-लाइन टूल के रूप में पर्ल के लिए बेहतर है और यह छोटे इंटरऑपरेबल प्रोग्राम्स को एकजुट और पठनीय प्रक्रियाओं में यूनिक्स दर्शन को गले लगाता है।
जॉन जेड

7

मिश्रण के लिए मेरी अपनी विविधता जोड़ना। मुझे लगता है कि यह बहुत सरल है और उपयोगी हो सकता है जब दक्षता कोई बड़ी चिंता नहीं है।

find . -type f | grep -o -E '\.[^\.]+$' | sort -u

1
पोर्टेबिलिटी के लिए +1, हालांकि रेगेक्स काफी सीमित है, क्योंकि यह केवल एक अक्षर से मिलकर एक्सटेंशन से मेल खाता है। स्वीकृत उत्तर से रेगेक्स का उपयोग करना बेहतर लगता है:$ find . -type f | grep -o -E '\.[^.\/]+$' | sort -u
mMontu

1
माना। मैं वहाँ से थोड़ा दूर चला गया। आपके द्वारा बताई गई गलती को ठीक करने के लिए मेरे उत्तर का संपादन।
gkb0986

ठंडा। मैं उद्धरणों को डबलक्वाट्स पर अपडेट करता हूं, grep biraries और निर्भरता को अपडेट करता हूं (क्योंकि गिट के साथ प्रदान किया गया है) और अब विंडोज़ के लिए यह काम करता है। लिनक्स उपयोगकर्ता की तरह लग रहा है।
मिसेज़ेल

5

पायथन में रिक्त एक्सटेंशन सहित बहुत बड़ी निर्देशिकाओं के लिए जनरेटर का उपयोग करते हुए, और प्रत्येक एक्सटेंशन को जितनी बार दिखाता है, उतनी बार प्राप्त होता है:

import json
import collections
import itertools
import os

root = '/home/andres'
files = itertools.chain.from_iterable((
    files for _,_,files in os.walk(root)
    ))
counter = collections.Counter(
    (os.path.splitext(file_)[1] for file_ in files)
)
print json.dumps(counter, indent=2)

5

मैंने यहाँ उत्तरों का एक गुच्छा आज़माया, यहाँ तक कि "सर्वश्रेष्ठ" उत्तर भी। वे सभी उस चीज से कम आए जो मैं विशेष रूप से था। तो पिछले 12 घंटों के अलावा regex कोड में कई कार्यक्रमों के लिए बैठना और इन उत्तरों को पढ़ना और परीक्षण करना यह वही है जो मैं लेकर आया हूं जो बिल्कुल वैसे ही काम करता है जैसे मैं चाहता हूं।

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
  • उन सभी फ़ाइलों को ढूँढता है जिनमें एक्सटेंशन हो सकता है।
  • केवल विस्तार पकड़ता है
  • 2 और 16 वर्णों के बीच फ़ाइल एक्सटेंशन के लिए चरण (यदि वे आपकी आवश्यकता के अनुरूप नहीं हैं तो बस संख्या समायोजित करें)। यह कैश फ़ाइलों और सिस्टम फ़ाइलों से बचने में मदद करता है (सिस्टम फ़ाइल बिट जेल की खोज करने के लिए है)।
  • निचले मामले में एक्सटेंशन प्रिंट करने के लिए जागें।
  • सॉर्ट करें और केवल अनन्य मानों में लाएं। मूल रूप से मैंने जाग उत्तर का प्रयास करने का प्रयास किया था, लेकिन यह उन वस्तुओं को प्रिंट करेगा जो केस सेंसिटिविटी में भिन्न हैं।

यदि आपको फ़ाइल एक्सटेंशन की गिनती की आवश्यकता है, तो नीचे दिए गए कोड का उपयोग करें

find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn

हालांकि इन विधियों को पूरा होने में कुछ समय लगेगा और शायद समस्या के बारे में जाने के सर्वोत्तम तरीके नहीं हैं, वे काम करते हैं।

अपडेट: प्रति @ अल्फा_989 लंबी फ़ाइल एक्सटेंशन एक समस्या का कारण होगा। यह मूल रेगेक्स "[[: अल्फा:]] {3,6}" के कारण है। मैंने रेगेक्स "[[: अल्फा:]]] {2,16}" को शामिल करने के उत्तर को अपडेट किया है। हालाँकि, इस कोड का उपयोग करने वाले किसी को भी इस बात की जानकारी होनी चाहिए कि वे संख्याएँ अधिकतम हैं और अंतिम आउटपुट के लिए एक्सटेंशन की अनुमति कब तक है। उस सीमा के बाहर कुछ भी आउटपुट में कई लाइनों में विभाजित हो जाएगा।

नोट: ओरिजिनल पोस्ट ने पढ़ा "- 3 और 6 अक्षरों के बीच फ़ाइल एक्सटेंशन के लिए ग्रीप्स (यदि वे आपकी ज़रूरत के अनुसार फिट नहीं हैं तो बस संख्याओं को समायोजित करें)। यह कैश फ़ाइलों और सिस्टम फ़ाइलों (सिस्टम फ़ाइल बिट जेल की खोज के लिए) से बचने में मदद करता है। "

आइडिया: एक विशिष्ट लंबाई पर फ़ाइल एक्सटेंशन खोजने के लिए इस्तेमाल किया जा सकता है:

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u

जहां 4 फाइल एक्सटेंशन लंबाई शामिल करने के लिए है और फिर उस लंबाई से परे किसी भी एक्सटेंशन को ढूंढें।


गणना संस्करण पुनरावर्ती है?
फर्नांडो मोंटोया

@Shinrai, सामान्य रूप से अच्छा काम करता है। लेकिन अगर आपके पास कुछ रैंडम फाइल एक्सटेंशन हैं जो वास्तव में लंबे हैं जैसे कि .download, तो यह ".download" को 2 भागों में तोड़ देगा और 2 फाइलों की रिपोर्ट करेगा, जो "downlo" है और दूसरी जो "ad" है
Alpha_989

@ अल्फ़ा_989, यह रेगेक्स के कारण है [[: अल्फ़ा:]] {3,6} "भी 3 वर्णों से छोटे एक्सटेंशन वाले किसी समस्या का कारण होगा। अपनी जरूरत के हिसाब से एडजस्ट करें। व्यक्तिगत रूप से मैं कहूंगा कि ज्यादातर मामलों में 2,16 को काम करना चाहिए।
शिन्राइ

जवाब देने के लिए धन्यवाद .. हाँ .. जो मुझे बाद में पता चला। यह अच्छी तरह से काम करने के बाद मैंने इसे आपके द्वारा उल्लिखित के समान संशोधित किया।
अल्फा_989

3

चूंकि पहले से ही एक और समाधान है जो पर्ल का उपयोग करता है:

यदि आपके पास पायथन स्थापित है तो आप भी कर सकते हैं (शेल से):

python -c "import os;e=set();[[e.add(os.path.splitext(f)[-1]) for f in fn]for _,_,fn in os.walk('/home')];print '\n'.join(e)"

2

अब तक कोई भी जवाब नए नामों के साथ फिल्म्स के साथ ठीक से व्यवहार नहीं करता (सिवाय क्रिस्टोफीडी के, जो अभी आया था क्योंकि मैं इसे टाइप कर रहा था)। निम्नलिखित एक खोल-लाइनर नहीं है, लेकिन काम करता है, और यथोचित तेज़ है।

import os, sys

def names(roots):
    for root in roots:
        for a, b, basenames in os.walk(root):
            for basename in basenames:
                yield basename

sufs = set(os.path.splitext(x)[1] for x in names(sys.argv[1:]))
for suf in sufs:
    if suf:
        print suf

2

मुझे नहीं लगता कि यह अभी तक उल्लेख किया गया था:

find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c

यह संभवतः प्रत्येक फ़ाइल के लिए एक नई प्रक्रिया पैदा करने के कारण काफी धीमा होगा।
ओन्ड्रा kaयूस्का

1

मुझे लगता है कि सबसे सरल और सीधा तरीका है

for f in *.*; do echo "${f##*.}"; done | sort -u

यह क्रिस्टोफ़ीड के 3 तरह से संशोधित है।


0

आप भी ऐसा कर सकते हैं

find . -type f -name "*.php" -exec PATHTOAPP {} +

0

मैंने इसे सरल और तेज़ पाया है ...

   # find . -type f -exec basename {} \; | awk -F"." '{print $NF}' > /tmp/outfile.txt
   # cat /tmp/outfile.txt | sort | uniq -c| sort -n > tmp/outfile_sorted.txt

0

स्वीकृत उत्तर REGEX का उपयोग करता है और आप REGEX के साथ एक उपनाम आदेश नहीं बना सकते हैं, आपको इसे एक शेल स्क्रिप्ट में डालना होगा, मैं Amazon Linux 2 का उपयोग कर रहा हूं और निम्नलिखित कार्य किया है:

  1. मैंने उपयोग किए गए उत्तर कोड को एक फ़ाइल में डाला:

    सुडो विम खोज.श

इस कोड को जोड़ें:

find ./ -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

टाइप करके फाइल सेव करें: :wq!

  1. sudo vim ~/.bash_profile

  2. alias getext=". /path/to/your/find.sh"

  3. :wq!

  4. . ~/.bash_profile

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