फ़ाइल में रखे गए रास्तों की सूची को पार्स करने के लिए बेसनेम का उपयोग करें


9

मैं मैक ओएसएक्स चला रहा हूं और उसी नाम के साथ मेरे पास मौजूद फाइलों की संख्या का पता लगाने के लिए कमांड लाइन का उपयोग करने की कोशिश कर रहा हूं।

मैंने निम्नलिखित कमांड का उपयोग करने की कोशिश की:

find ~ -type f -name "*" -print | basename | sort | uniq -d > duplicate_files

यह काम नहीं करता है! जब मैं निम्नलिखित कार्य करता हूं:

find ~ -type f -name "*" -print > duplicate_files

तब डुप्लिकेट_फाइल्स में मेरी सभी फ़ाइलों के पथ होते हैं। इसलिए मुझे लगता है कि मुद्दा साथ है basename- यह मानक इनपुट को स्वीकार नहीं करता है। मैंने तब निम्नलिखित कोशिश की:

basename $(find ~ -type f -name "*" -print) > duplicate_files

लेकिन फिर से वह काम नहीं करता है। इंटरनेट पर सर्च करने से ज्यादा खुशी नहीं मिलती है। किसी भी विचार सबसे स्वागत करते हैं।

जवाबों:


16

basename अपने कमांड लाइन तर्क पर काम करता है, यह मानक इनपुट से नहीं पढ़ता है।

आपको basenameउपयोगिता को कॉल करने की आवश्यकता नहीं है , और आप बेहतर नहीं करेंगे: यह सब करना होगा अंतिम से पहले भाग को अलग करना है /, और प्रत्येक प्रविष्टि के लिए एक बाहरी कमांड को कॉल करना धीमा होगा, आप एक टेक्स्ट प्रोसेसिंग का उपयोग कर सकते हैं इसके बजाय उपयोगिता।

find ~ -type f | sed 's!.*/!!' | sort | uniq -d

यह फ़ाइलों के स्थान का ट्रैक रखने के लिए अधिक उपयोगी हो सकता है। नाम से छाँटने से डुप्लिकेट का पता लगाना आसान हो जाता है, लेकिन sortअंतिम फ़ील्ड का उपयोग करने का विकल्प नहीं होता है। आप जो कर सकते हैं वह अंतिम /-पारंक्षित फ़ील्ड को शुरुआत में कॉपी करें , फिर सॉर्ट करें, और फिर डुप्लिकेट को निकालने और प्रस्तुत करने के लिए थोड़े-थोड़े तदर्थ के प्रसंस्करण का उपयोग करें।

find ~ -type f |
sed 's!.*/\(.*\)!\1/&!' |   # copy the last field to the beginning
sort -t/ -k1,1 |
cut -d/ -f2- |   # remove the extra first field (could be combined with awk below)
awk -F / '{
    if ($NF == name) {
        if (previous != "") {print previous; previous = ""}
        print
    } else {
        previous = $0
        name = $NF
    }
'

(ध्यान दें कि मैं मानता हूं कि आपकी फ़ाइल के किसी भी नाम में newline वर्ण नहीं हैं।)


सुपर धन्यवाद। यह वही है जो मैं करने की कोशिश कर रहा था ... बहुत उपयोगी
जॉन 3:10

7

क्यों findसिर्फ फ़ाइल नाम के उत्पादन के लिए अंतर्निहित सुविधाओं का उपयोग न करें :

find ~ -type f -printf '%f\n' | sort | uniq -c

(ग्नू मानता है find) या कम से कम कुछ इस तरह:

find ~ -exec basename {} \; | sort | uniq -c

basename पाइप के माध्यम से नहीं पढ़ सकते हैं या एक साथ कई फ़ाइलों को प्रोसेस नहीं कर सकते हैं।

ps। -name '*'यदि आप सभी फ़ाइलों को सूचीबद्ध करना चाहते हैं, तो निर्दिष्ट करने की कोई आवश्यकता नहीं है । यह एक डिफ़ॉल्ट विकल्प है।


धन्यवाद - UN -printf ’OS X UNIX
JohnB

और जब मैं दूसरे संस्करण की कोशिश करता हूं तो मुझे मिलता है basename: unknown primary or operator। टिप के लिए धन्यवाद-name "*"
जॉन्स

वह अजीब है। मैं -printfपॉज़िक्स मैन पेज में भी देख सकता हूं । दूसरे तरीके से त्रुटि के बारे में, यह मेरे उत्तर में टाइपो का कारण है। फिक्स्ड। क्या आप इसे एक बार और आज़मा सकते हैं?
भीड़

इसके साथ ही -printfमुझे मिलता है -printf: unknown primary or operator। इसके अलावा जब मैंने यूनिक्स की जाँच संक्षेप में की गई एक संदर्भ पुस्तक में की तो वह एक GNU / Linux विकल्प के रूप में सूचीबद्ध है - OSX के बारे में कुछ भी नहीं कहता
JohnB

1
वास्तव में सबसे अच्छा स्रोत हो सकता है man findअपने कंसोल :) में
भीड़

4

यह मेरे लिए OSX पर काम करता है:

find ~ -type f -exec basename -a {} + | sort | uniq -d

हां - यह बहुत धन्यवाद है - ब्याज से बाहर +कमान में क्या संकेत देता है?
जॉन बी

2
क्या यह उपयोगी है कृपया इस पर विचार करें।
सस्पेन्स

यह है - मैं वोट नहीं कर सकते beacuase मैं 15 प्रतिष्ठा की जरूरत है :-(
JohnB

@StephaneChazelas: BSD बेसन के लिए मैन पेज के अनुसार , निष्पादन योग्य कई तर्कों को तर्क के रूप में ले सकता है। मैंने OSX पर डबल चेक किया, यह काम करता है।
रहमू

1
सब ठीक है, मैं सही खड़ा हूँ। मुझे उस बीएसडी एक्सटेंशन के बारे में पता नहीं था। हालाँकि, अभी भी विफल रहता है अगर वहाँ बिल्कुल दो फ़ाइलें हैं। आपको उस मामले के लिए भी कवर करने का -aविकल्प जोड़ना होगा ।
स्टीफन चेजालस


2

आप उपयोग कर सकते हैं xargsके साथ basenameइस तरह, वांछित उत्पादन प्राप्त करने के लिए:

find ~ -type f -name "*" -print | xargs -l basename | sort | uniq -d > duplicate_files

0

bashसाहचर्य सरणियों को संभालने वाले हाल के संस्करण के साथ , इसके अतिरिक्त एम्बेडेड न्यूलाइन्स के साथ पथनाम भी संभालेंगे:

#!/bin/bash

topdir=$HOME

shopt -s globstar  # enable the ** glob

declare -A count

# count the number of times each filename (base name) occurs
for pathname in "$topdir"/**; do
    # skip names that are not regular files (or not symbolic links to such files)
    [ ! -f "$pathname" ] && continue

    # get the base name
    filename=${pathname##*/}

    # add one to this base name's count
    count[$filename]=$(( ${count[$filename]} + 1 ))
done

# go through the collected names and print any name that
# has a count greater than one
for filename in "${!count[@]}"; do
    if [ "${count[$filename]}" -gt 1 ]; then
        printf 'Duplicate filename: %s\n' "$filename"
    fi
done

यह कोई बाहरी उपयोगिता का उपयोग करता है।

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