उपनिर्देशिका और समय के साथ निर्देशिका में नवीनतम संशोधित फ़ाइलों को कैसे खोजा और सूचीबद्ध किया जाए?


417
  • ऑपरेटिंग सिस्टम: लिनक्स

  • फाइलसिस्टम प्रकार: ext3

  • पसंदीदा समाधान: बैश (स्क्रिप्ट / ऑनलाइनर), माणिक, अजगर

मैं कई उपनिर्देशिकाओं और उन में फ़ाइलों के साथ कई निर्देशिकाएं हैं। मुझे इन सभी निर्देशिकाओं की एक सूची बनाने की जरूरत है जो इस तरह से बनाई गई है कि हर पहली-स्तरीय निर्देशिका को उसके भीतर नवीनतम निर्मित / संशोधित फ़ाइल की तारीख और समय के बगल में सूचीबद्ध किया गया है।

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

./alfa/beta/gamma/example.txt

और मैं फ़ाइल की सामग्री को संशोधित करता example.txtहूं, मुझे उस समय की आवश्यकता है जो alfaमानव पठनीय रूप में प्रथम-स्तरीय निर्देशिका के बगल में प्रदर्शित हो, न कि युगांतरकारी। मैंने कुछ चीजों को खोजने की कोशिश की है xargs, sortऔर पसंद की, लेकिन मैं इस समस्या के आसपास नहीं पहुंच सकता कि जब मैं फ़ाइलों को कुछ स्तरों को बनाता / संशोधित करता हूं, तो 'अल्फा' का फाइल सिस्टम टाइमस्टैम्प नहीं बदलता।


यदि आप इसे बनाने का दर्द उठा सकते हैं, तो github.com/shadkam/recentmost का उपयोग किया जा सकता है।
user3392225

4
अतुल्य। 16 उत्तर, और अधिकांश / सभी भी ओपी को निर्दिष्ट करने की कोशिश नहीं करते हैं ...
हमीज ने इस्तीफा दे दिया

समाधान जैसे आर-आर स्विच के बजाय, मैं सिर्फ यहां थोक देखता हूं।
neverMind9

एक देशी सुविधा होनी चाहिए।
neverMind9

जवाबों:


486

इसको आजमाओ:

#!/bin/bash
find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head

निर्देशिका के पथ के साथ इसे निष्पादित करें जहां इसे पुनरावर्ती रूप से स्कैन करना शुरू करना चाहिए (यह रिक्त स्थान के साथ फ़ाइलनाम का समर्थन करता है)।

यदि बहुत सारी फाइलें हैं, तो कुछ भी लौटने से पहले इसमें कुछ समय लग सकता है। यदि हम xargsइसके बजाय उपयोग करते हैं तो प्रदर्शन में सुधार किया जा सकता है :

#!/bin/bash
find $1 -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head

जो थोड़ा तेज है।


132
आपका "फास्ट मेथड" भी रिक्त स्थान का समर्थन करने के लिए Print0 का उपयोग करने में सक्षम होना चाहिए और यहां तक ​​कि फ़ाइल नाम में फीडफीड भी होना चाहिए। यहाँ मैं क्या उपयोग find $1 -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head करता हूँ: यह अभी भी मेरे लिए उपवास करने का प्रबंधन करता है।
दान

20
Mac OS X पर यह GNU का स्टेट नहीं है, इसलिए कमांड विफल रहता है। आपको इसके बजाय brew install coreutilsउपयोग gstatकरना होगाstat
चार्ल्स बी

36
आपको काम करने की आवश्यकता नहीं है statक्योंकि find PATH -type f -printf "%T@ %p\n"| sort -nrयह काम करता है। यह उस तरह से थोड़ा तेज भी है।
एनआर

4
क्या हम किसी तरह से @ user37078 की टिप्पणी को वास्तविक उत्तर में बदल सकते हैं या मूल उत्तर को संपादित कर सकते हैं? ऐसा लगता है कि यह "सही तरीका" [tm] है।
मेंगल जू

6
मैक ओएस एक्स पर, बिना गस्टैट या कुछ और स्थापित किए बिना, आप कर सकते हैं:find PATH -type f -exec stat -f "%m %N" "{}" \; | sort -nr | head
कोबज़िला

198

उन सभी फ़ाइलों को खोजने के लिए जो फ़ाइल की स्थिति को अंतिम बार N मिनट पहले बदल दिया गया था:

find -cmin -N

उदाहरण के लिए:

find -cmin -5


4
+1 धन्यवाद, बहुत उपयोगी है। GnuWin32 खोज का उपयोग करके विंडोज पर काम करता है।
सबुनकु

बहुत ही प्रचलित। बहुत अच्छा!
रैंडी एल

यह अन्य समाधानों की तुलना में अधिक जटिल है
david.perez

20
वास्तव में अच्छा है, आप पिछले 50 दिनों के बदलाव के लिए 'खोज -ctime -50' का भी उपयोग कर सकते हैं।
गोरकेम

1
अव्यवस्था को बाहर करने के लिए, का उपयोग करेंsudo find -cmin -1 2>&1 |grep -v /proc/
Cees Timmerman

39

जीएनयू फाइंड (देखें man find) में -printfईपीओसी माइम और रिलेटिव पाथ नेम को डिलीट करने के लिए एक पैरामीटर है।

redhat> find . -type f -printf '%T@ %P\n' | sort -n | awk '{print $2}'

3
धन्यवाद! यह एकमात्र उत्तर है जो उचित समय में मेरी बहुत विस्तृत निर्देशिका संरचना के माध्यम से खोज करने के लिए पर्याप्त है। मैं आउटपुट tailको हजारों लाइनों को आउटपुट में प्रिंट होने से रोकने के लिए पास करता हूं ।
sffc

8
एक अन्य टिप्पणी: यह awk '{print $2}'भाग उन मुद्दों का कारण बनता है जब रिक्त स्थान के साथ फ़ाइल नाम हैं। sedइसके बजाय इसका उपयोग करने का एक उपाय है , और यह पथ के अतिरिक्त समय को भी प्रिंट करता है:find . -type f -printf '%T@ %Tc %P\n' | sort -n | tail | sed -r 's/^.{22}//'
sffc

3
मुझे लगता है कि यह क्रमबद्ध होना चाहिए
Bojan Dević

2
-प्रिंटफ वैरिएंट हर बार 'स्टेट' प्रक्रिया को कॉल करने की तुलना में बहुत तेज है - यह मेरी बैकअप नौकरी (ओं) को काट देता है। मुझे इससे अवगत कराने के लिए धन्यवाद। मैं awk / sed चीज से बचता हूं क्योंकि मैं केवल पेड़ के भीतर अंतिम अपडेट के बारे में चिंतित हूं - इसलिए X = $ (पाएं / पाथ-एफ fprintf '% T% p \ n' | grep -v something-I- don-tcare-about | Sort -nr। हेड-एन 1) और एक गूंज $ {X # * ""} ने मेरे लिए अच्छा काम किया (मुझे पहले स्थान तक सामान दें)
डेविड गुडविन

2
कई लाइन में फ़ाइल नाम होने पर सभी काम नहीं करेंगे। touch "lala<Enter>b"ऐसी फ़ाइल बनाने के लिए उपयोग करें । मुझे लगता है कि यूनिक्स यूटिलिटीज़ डिज़ाइन में फ़ाइलनाम के बारे में बड़ा दोष है।
फल

35

मैंने इस एक-लाइनर के लिए हेलो के भयानक जवाब को छोटा कर दिया

stat --printf="%y %n\n" $(ls -tr $(find * -type f))

अपडेट किया गया : यदि फ़ाइल नाम में स्थान हैं, तो आप इस संशोधन का उपयोग कर सकते हैं

OFS="$IFS";IFS=$'\n';stat --printf="%y %n\n" $(ls -tr $(find . -type f));IFS="$OFS";

इसके बारे में कैसे: IFS = $ '\ n'; stat --printf = "% y% n \ n" $ (ls -tr $ (find -type f))
slashdottir

3
यदि आपके पास बहुत बड़ी संख्या में फाइलें हैं, तो यह काम नहीं करेगा। xargs का उपयोग करने वाले उत्तर उस सीमा को हल करते हैं।
कार्ल वर्बेस्ट

@carlverbiest वास्तव में बड़ी संख्या में फाइलें स्लैशडॉटिर के समाधान को तोड़ देगा। तब भी xargs- आधारित समाधान धीमा होगा। user2570243 का समाधान बड़े फाइल सिस्टम के लिए सबसे अच्छा है।
स्टीफन गौरिचोन

IFS=$'\n'फ़ाइल नाम संभालते समय किसी भी घटना में सुरक्षित नहीं है: UNIX पर फ़ाइल नाम में नए वर्ण मान्य वर्ण हैं। केवल एनयूएल चरित्र को एक मार्ग में उपस्थित नहीं होने की गारंटी है।
चार्ल्स डफी

17

इसे इस्तेमाल करे

#!/bin/bash
stat --format %y $(ls -t $(find alfa/ -type f) | head -n 1)

यह findनिर्देशिका से सभी फ़ाइलों को इकट्ठा करने के लिए उपयोग करता है, lsउन्हें संशोधन की तारीख के आधार पर क्रमबद्ध करने के लिए, headपहली फ़ाइल का चयन करने के लिए और अंत statमें समय को एक अच्छे प्रारूप में दिखाने के लिए।

इस समय यह उनके नाम पर व्हॉट्सएप या अन्य विशेष वर्ण वाली फाइलों के लिए सुरक्षित नहीं है। यदि यह आपकी आवश्यकताओं को पूरा नहीं करता है तो एक प्रशंसा लिखें।


1
प्रभामंडल: मुझे आपका उत्तर पसंद है, यह अच्छी तरह से काम करता है और सही फ़ाइल को प्रिंट करता है। मैं हालांकि मेरी मदद नहीं करता, क्योंकि मेरे मामले में बहुत सारे आत्मघाती हैं। इसलिए मुझे ls के लिए "तर्क सूची बहुत लंबी है" ... और xargs इस मामले में भी मदद नहीं करेगा। मैं कुछ और कोशिश करूँगा।
फ्रेड्रिक

उस मामले में यह थोड़ा अधिक जटिल है और इसे कुछ वास्तविक कार्यक्रम की आवश्यकता होगी। मैं कुछ पर्ल को हैक कर लूंगा।
डैनियल बॉमर

1
मैंने इसके बजाय PHP का उपयोग करके इसे हल किया। एक पुनरावर्ती फ़ंक्शन जो फ़ाइल सिस्टम ट्री के माध्यम से उतरता है और सबसे हाल ही में संशोधित फ़ाइल का समय संग्रहीत करता है।
fredrik

11

यह कमांड Mac OS X पर काम करता है:

find "$1" -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head

लिनक्स पर, जैसा कि मूल पोस्टर ने पूछा था, के statबजाय का उपयोग करें gstat

यह उत्तर, निश्चित रूप से, उपयोगकर्ता 37078 के बकाया समाधान है, टिप्पणी से पूर्ण उत्तर तक प्रचारित किया गया। मैं में मिश्रित CharlesB के उपयोग करने के लिए अंतर्दृष्टि gstatपर मैक ओएस एक्स मुझे मिल गया coreutils से MacPorts बजाय homebrew , वैसे।

और यहाँ मैंने इसे ~/bin/ls-recent.shपुनः प्रयोग के लिए एक साधारण कमांड में कैसे पैक किया :

#!/bin/bash
# ls-recent: list files in a dir tree, most recently modified first
#
# Usage: ls-recent path [-10 | more]
# 
# Where "path" is a path to target directory, "-10" is any arg to pass
# to "head" to limit the number of entries, and "more" is a special arg
# in place of "-10" which calls the pager "more" instead of "head".
if [ "more" = "$2" ]; then
   H=more; N=''
else
   H=head; N=$2
fi

find "$1" -type f -print0 |xargs -0 gstat --format '%Y :%y %n' \
    |sort -nr |cut -d: -f2- |$H $N

2
ओएस एक्स yosemite पर; मुझे त्रुटि मिलती है: ढूँढें: ftsopen: ऐसी कोई फ़ाइल या निर्देशिका नहीं है
Reece

दिलचस्प। आपने कौन सा कमांड टाइप किया (मापदंडों के साथ)? और उस निर्देशिका में फ़ाइलों के नाम क्या थे? और अगर आपने अपना स्वयं का संस्करण बनाया है ~/bin/ls-recent.sh, तो क्या आपने मतभेदों के लिए स्क्रिप्ट की सावधानीपूर्वक जांच की है?
जिम डेलाउंट

10
उन लोगों के लिए जो मैक ओएस एक्स पर कुछ भी स्थापित नहीं करना चाहते हैं:find . -exec stat -f '%m%t%Sm %N' {} + | sort -n | cut -f2-
जेक

5

इस पोस्ट में दोनों पर्ल और पायथन समाधान ने मुझे मैक ओएस एक्स पर इस समस्या को हल करने में मदद की: /unix/9247/how-to-list-files-sorted-by-modification-date-recursively -नो-स्टेट-कमांड-लाभ

पोस्ट से उद्धरण:

पर्ल:

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

अजगर:

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'

5

छिपी हुई फ़ाइलों को अनदेखा करना - अच्छा और तेज़ समय टिकट के साथ

फ़ाइल नाम में रिक्त स्थान को अच्छी तरह से संभालता है - ऐसा नहीं है कि आपको उन का उपयोग करना चाहिए!

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

2017.01.28 07h00 Sat ./recent
2017.01.21 10h49 Sat ./hgb
2017.01.16 07h44 Mon ./swx
2017.01.10 18h24 Tue ./update-stations
2017.01.09 10h38 Mon ./stations.json

findलिंक का अनुसरण करके अधिक प्रचुरता पाई जा सकती है।


3

मैं इसे नवीनतम एक्सेस समय के लिए दिखा रहा हूं, आप नवीनतम मॉड टाइम करने के लिए इसे आसानी से संशोधित कर सकते हैं।

ऐसा करने के दो तरीके हैं:


1) यदि आप वैश्विक छंटनी से बचना चाहते हैं, जो महंगी हो सकती है यदि आपके पास लाखों फाइलें हैं, तो आप ऐसा कर सकते हैं: (अपने आप को उस निर्देशिका की जड़ में रखें जहाँ आप अपनी खोज शुरू करना चाहते हैं)

linux> touch -d @0 /tmp/a;
linux> find . -type f -exec tcsh -f -c test `stat --printf="%X" {}` -gt  `stat --printf="%X" /tmp/a`  ; -exec tcsh -f -c touch -a -r {} /tmp/a ; -print 

उपरोक्त विधि उत्तरोत्तर नए एक्सेस समय के साथ फ़ाइल नाम प्रिंट करती है और अंतिम फ़ाइल जो प्रिंट करती है वह नवीनतम एक्सेस टाइम वाली फाइल है। आप स्पष्ट रूप से "पूंछ -1" का उपयोग करके नवीनतम एक्सेस समय प्राप्त कर सकते हैं।


2) आप अपने उपनिर्देशिका में सभी फ़ाइलों का उपयोग समय, नाम का पुनरावर्ती प्रिंट कर सकते हैं और फिर पहुंच समय और पूंछ सबसे बड़ी प्रविष्टि के आधार पर छाँट सकते हैं:

linux> \find . -type f -exec stat --printf="%X  %n\n" {} \; | \sort -n | tail -1

आखिर तुमने इसे हासिल कर ही लिया है...


3

मेरे पास मेरे लाभ में यह उर्फ ​​है जो मैं अक्सर उपयोग करता हूं

$ alias | grep xlogs
xlogs='sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R'

तो यह वही है जो आप खोज रहे हैं (अपवाद के साथ यह समय / समय कई स्तरों को बदल नहीं सकता है) - इस मामले में नवीनतम फ़ाइलों (* .log और * .trc फ़ाइलों) की तलाश करता है; यह भी केवल अंतिम दिन में संशोधित फ़ाइलों को पाता है, फिर समय के अनुसार क्रमबद्ध होता है और कम से पाइप उत्पादन करता है:

sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R

ps। ध्यान दें कि मेरे पास कुछ सर्वरों पर रूट नहीं है, लेकिन हमेशा sudo है, इसलिए आपको उस हिस्से की आवश्यकता नहीं हो सकती है।


यह "वास्तव में आप क्या देख रहे हैं" कैसे है? ओपी ने एक अच्छी व्याख्या लिखी कि वह क्या चाहता है, और यह पूरी तरह से इसे अनदेखा करता है।
हमीजेल

उस ओर इशारा करने के लिए धन्यवाद। आप सही हैं - यह तरीका परिवर्तन की तारीख / समय प्राप्त करने के लिए कई स्तरों पर नहीं जाता है, यह केवल निर्देशिकाओं की फाइलों की तारीख / समय दिखाता है। मेरा जवाब संपादित किया।
तगर

1

आप एक कोशिश खोजने के लिए printf कमांड दे सकते हैं

K द्वारा निर्दिष्ट प्रारूप में% Ak फ़ाइल का अंतिम अभिगमन समय, जो या तो @' or a directive for the C स्ट्रैफ़ाइम फ़ंक्शन है। K के लिए संभावित मान नीचे सूचीबद्ध हैं; उनमें से कुछ सिस्टम के बीच `strftime 'में अंतर के कारण सभी प्रणालियों पर उपलब्ध नहीं हो सकते हैं।


1

त्वरित बैश समारोह:

# findLatestModifiedFiles(directory, [max=10, [format="%Td %Tb %TY, %TT"]])
function findLatestModifiedFiles() {
    local d="${1:-.}"
    local m="${2:-10}"
    local f="${3:-%Td %Tb %TY, %TT}"

    find "$d" -type f -printf "%T@ :$f %p\n" | sort -nr | cut -d: -f2- | head -n"$m"
}

निर्देशिका में नवीनतम संशोधित फ़ाइल खोजें:

findLatestModifiedFiles "/home/jason/" 1

आप तीसरे तर्क के रूप में अपनी तिथि / समय प्रारूप भी निर्दिष्ट कर सकते हैं।


1

निम्नलिखित आपको टाइम-स्टैम्प का एक स्ट्रिंग और सबसे हाल के टाइम-स्टैम्प के साथ फ़ाइल का नाम देता है:

find $Directory -type f -printf "%TY-%Tm-%Td-%TH-%TM-%TS %p\n" | sed -r 's/([[:digit:]]{2})\.([[:digit:]]{2,})/\1-\2/' |     sort --field-separator='-' -nrk1 -nrk2 -nrk3 -nrk4 -nrk5 -nrk6 -nrk7 | head -n 1

फॉर्म के आउटपुट में परिणाम: <yy-mm-dd-hh-mm-ss.nanosec> <filename>


1

यहाँ एक संस्करण है जो फ़ाइल नाम के साथ काम करता है जिसमें रिक्त स्थान, newlines, ग्लोब वर्ण भी हो सकते हैं:

find . -type f -printf "%T@ %p\0" | sort -zk1nr
  • find ... -printfप्रिंट एक स्थान और उसके बाद \0फाइलनेम को संशोधित करता है ।
  • sort -zk1nr एनयूएल समाप्त डेटा पढ़ता है और इसे संख्यात्मक रूप से उल्टा करता है

चूंकि प्रश्न लिनक्स के साथ टैग किया गया है इसलिए मैं मान रहा हूं gnu बर्तन उपलब्ध हैं।

आप इसके साथ ऊपर पाइप कर सकते हैं:

xargs -0 printf "%s\n"

संशोधन समय और फ़ाइल नाम को प्रिंट करने के लिए संशोधन समय (सबसे हाल ही में पहले) को न्यूलाइन द्वारा समाप्त किया गया।


1

यह वही है जो मैं उपयोग कर रहा हूं (बहुत कुशल):

function find_last () { find "${1:-.}" -type f -printf '%TY-%Tm-%Td %TH:%TM %P\n' 2>/dev/null | sort | tail -n "${2:-10}" }

पेशेवरों:

  • यह केवल 3 प्रक्रियाओं को जन्म देता है

उपयोग:

find_last [dir [number]]

कहाँ पे:

  • dir - खोज की जाने वाली एक निर्देशिका [वर्तमान dir]
  • number - प्रदर्शित करने के लिए नवीनतम फ़ाइलों की संख्या [10]

find_last /etc 4इस तरह दिखता है आउटपुट :

2019-07-09 12:12 cups/printers.conf
2019-07-09 14:20 salt/minion.d/_schedule.conf
2019-07-09 14:31 network/interfaces
2019-07-09 14:41 environment

0

सादे lsआउटपुट के लिए, इसका उपयोग करें। कोई तर्क सूची नहीं है, इसलिए यह बहुत लंबा नहीं हो सकता है:

find . | while read FILE;do ls -d -l "$FILE";done

और cutसिर्फ तारीखों, समय और नाम के साथ अच्छा किया गया:

find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5

संपादित करें : बस ध्यान दिया गया है कि वर्तमान शीर्ष उत्तर संशोधन तिथि के अनुसार है। यह यहाँ दूसरे उदाहरण के साथ आसान है, क्योंकि संशोधन तिथि प्रत्येक पंक्ति में पहली बार है - अंत में एक प्रकार का थप्पड़:

find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5 | sort

0

यह बैश में भी एक रसीद समारोह के साथ किया जा सकता है

F को एक ऐसा फंक्शन दें जो फ़ाइल के समय को प्रदर्शित करता है जो कि lexicographically सॉर्ट करने योग्य yyy-mm-dd आदि होना चाहिए, (os- निर्भर?)

F(){ stat --format %y "$1";}                # Linux
F(){ ls -E "$1"|awk '{print$6" "$7}';}      # SunOS: maybe this could be done easier

निर्देशिका के माध्यम से चलने वाले पुनरावर्ती फ़ंक्शन को आर

R(){ local f;for f in "$1"/*;do [ -d "$f" ]&&R $f||F "$f";done;}

और अंत में

for f in *;do [ -d "$f" ]&&echo `R "$f"|sort|tail -1`" $f";done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.