linux 修改子目录名称,关于Linux:如何递归地查找和列出具有子目录和时间的目录中最新修改的文件?...

操作系统:Linux

文件系统类型:ext3

首选解决方案:bash(script/oneliner)、ruby、python

我有几个目录,其中有几个子目录和文件。我需要列出所有这些目录,这些目录的构造方式使得每个一级目录都列在其中最新创建/修改文件的日期和时间旁边。

为了澄清,如果我触摸一个文件或者向下修改它的内容几个子目录级,那么时间戳应该显示在第一级目录名的旁边。假设我有一个这样的目录:

./alfa/beta/gamma/example.txt

我修改了文件example.txt的内容,我需要在第一级目录alfa旁边以人类可读的形式显示时间,而不是时代。我用find、xargs、sort等工具尝试过一些方法,但我不能解决当我创建/修改几个级别的文件时文件系统时间戳"alfa"不变的问题。

如果您能忍受构建它的痛苦,可以使用github.com/shadkam/recentmost。

简直不可思议。16个答案,而且大多数/全部都不会尝试去做OP指定的事情…

我看到的不是像A-R开关这样的解决方案,而是大量的。

试试这个:

#!/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

速度快一点。

您的"快速方法"还应该能够使用print0来支持文件名中的空格甚至换行符。我用的是:find $1 -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head,这对我来说仍然很快。

我正在查找的一些目录不允许我使用stat目录,因此我进行了以下更改(对"fast"目录),因此我不必查看最终输出中的错误。find ${1} -type f | xargs stat --format '%Y :%y %n' 2>/dev/null | sort -nr | cut -d: -f2-

这对于弄清楚为什么我的NAS硬盘一直在唤醒非常有帮助。有人能推荐一个类似的替代方案,将结果限制在X天之内吗?(即相同类型的列表,但仅限于最近24小时内修改的文件)?

在MacOSX上,它不是GNU的stat,所以命令失败。你必须使用brew install coreutils和gstat而不是stat。

你不需要运行stat,因为find PATH -type f -printf"%T@ %p

"| sort -nr完成了任务。那样的话,速度也会快一点。

我们能否将@user37078的评论转换为实际答案或编辑原始答案?这似乎是"正确的方法"[tm]。

查找5分钟前最后一次更改文件状态的所有文件:find -cmin -5。

@用户37078那个快速版本应该是它自己的答案,我赞成。

此外,如果您希望显示的内容超过默认值,请在"head"命令上抛出-n。

在Mac OS X上,无需安装gstat或其他任何操作,您可以执行以下操作:find PATH -type f -exec stat -f"%m %N""{}" \; | sort -nr | head

关于Debian Jessie stat: missing operand

这不会像op asked那样列出目录,而是列出文件。

要查找上次在n分钟前更改文件状态的所有文件,请执行以下操作:

find -cmin -N

例如:

find -cmin -5

+1谢谢,非常有用。使用gnuwin32 find在Windows上工作。

非常简洁。很不错的!

它比其他更复杂的解决方案更快

非常好,还可以使用"find-ctime-50"作为最近50天的更改。

为了排除杂波,使用sudo find -cmin -1 2>&1 |grep -v /proc/。

最佳且简单的解决方案…

gnu find(见man find有一个-printf参数,用于显示文件epoc mtime和相对路径名。

redhat> find . -type f -printf '%T@ %P

' | sort -n | awk '{print $2}'

谢谢!这是唯一一个足够快的答案,可以在合理的时间内搜索我非常宽的目录结构。我通过tail传递输出,以防止在输出中打印数千行。

另一条评论是:当文件名带有空格时,awk '{print $2}'部分似乎会引起问题。这里有一个使用sed的解决方案,它除了打印路径外还打印时间:find . -type f -printf '%T@ %Tc %P

' | sort -n | tail | sed -r 's/^.{22}//'

我认为应该是排序-rn

printf变量比每次调用一个"stat"进程都快得多,它可以缩短备份工作的时间。谢谢你让我意识到这一点。我避免了awk/sed的问题,因为我只关心树中的最后一次更新,所以x=$(find/path-type f-printf%t%p'grep-v so me thing-i-don-tcare-about sort-nr head-n 1)和echo$x*""(给我第一个空间的内容)

如果文件名跨多行,则所有文件都不起作用。使用touch"lalab"创建此类文件。我认为Unix实用程序设计在文件名方面有很大的缺陷。

我缩短了Halo对这一行的精彩回答

stat --printf="%y %n

" $(ls -tr $(find * -type f))

更新:如果文件名中有空格,可以使用此修改

OFS="$IFS";IFS=$'

';stat --printf="%y %n

" $(ls -tr $(find . -type f));IFS="$OFS";

如果文件或目录的名称中包含空格,则将不起作用…

如何处理:ifs=$'';stat--printf="%y%n"$(ls-tr$(find)。F型)

如果您有大量的文件,这将不起作用。使用xargs的答案解决了这个限制。

@事实上,大量文件会破坏Slashdottir的解决方案。即使是基于xargs的解决方案也会很慢。用户2570243的解决方案最适合大型文件系统。

在处理文件名时,IFS=$'

'在任何情况下都是不安全的:在Unix上,换行符是文件名中的有效字符。只有nul字符才能保证不会出现在路径中。

试试这个

#!/bin/bash

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

它使用find从目录中收集所有文件,ls列出按修改日期排序的文件,head选择第一个文件,最后用stat以良好的格式显示时间。

此时,对于名称中带有空格或其他特殊字符的文件来说,这是不安全的。如果还不能满足你的需要,写一封推荐信。

哈洛:我喜欢你的答案,它很好地工作,并打印出正确的文件。不过,我没有帮助我,因为我的案件中有太多的转租。所以我得到的"参数列表太长"为ls…在这种情况下,xargs也无济于事。我再试试别的。

在这种情况下,它有点复杂,需要一些真正的程序。我要砍一些珍珠。

我用PHP解决了这个问题。一个递归函数,通过文件系统树下降并存储最近修改的文件的时间。

此命令在Mac OS X上工作:

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

在Linux上,正如最初的海报所要求的那样,使用stat而不是gstat。

当然,这个答案是用户37078出色的解决方案,从评论提升到了完整的答案。我混合了Charlesb在MacOSX上使用gstat的见解,顺便说一下,我从MacPorts获得了coreutils,而不是自制的。

下面是我如何将它打包成一个简单的命令~/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

在OS X Yosemite上;我得到错误:find:ftsopen:没有这样的文件或目录

有趣。您键入了什么命令(带参数)?那个目录中的文件名是什么?如果您创建了自己的~/bin/ls-recent.sh版本,您是否仔细检查了脚本的差异?

对于那些不想在Mac OS X上安装任何东西的用户:find . -exec stat -f '%m%t%Sm %N' {} + | sort -n | cut -f2-

本文中的Perl和Python解决方案都帮助我在Mac OS X上解决了这个问题:https://unix.stackexchange.com/questions/9247/how-to-list-files-sorted-by-modification-date-recursively-no-stat-command-availy。

从文章中引用:

Perl:

find . -type f -print |

perl -l -ne '

$_{$_} = -M;  # store file age (mtime - now)

END {

$,="

";

print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age

}'

Python:

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'

它按修改日期排序,但按字母顺序排列,即四月……八月…

我在显示最新的访问时间,你可以很容易地修改这个做最新的修改时间。

有两种方法可以做到这一点:

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

上面的方法以逐渐更新的访问时间打印文件名,它打印的最后一个文件是具有最新访问时间的文件。显然,您可以使用"tail-1"获得最新的访问时间。

2)您可以找到递归打印子目录中所有文件的名称、访问时间,然后根据访问时间和尾部排序最大的条目:

linux> \find . -type f -exec stat --printf="%X  %n

" {} \; | \sort -n | tail -1

就在这里,你有它……

我的.profile中有这个别名,我经常使用它

$ alias | grep xlogs

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

因此,它执行您正在查找的操作(但不遍历多个级别的更改日期/时间)-查找最新的文件(本例中为日志文件和*.trc文件);此外,它只查找在最后一天修改的文件,然后按时间排序,并通过更少的管道输出:

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

注意,有些服务器上没有根目录,但总是有sudo,所以您可能不需要这个部分。

"你到底在找什么"这是怎么回事?这篇文章很好地解释了他想要什么,但这完全忽略了。

谢谢你的指点。您是正确的-这个方法不需要多个级别来获取更改日期/时间,它只显示其中目录文件的日期/时间。编辑了我的答案。

忽略隐藏的文件-具有良好和快速的时间戳

文件名中的空格处理得很好-不应该使用这些空格!

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p

' |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

通过链接可以找到更多的findgalore。

快速撞击功能:

# 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

" | sort -nr | cut -d: -f2- | head -n"$m"

}

在目录中查找最新修改的文件:

findLatestModifiedFiles"/home/jason/" 1

您还可以将自己的日期/时间格式指定为第三个参数。

下面返回一个时间戳字符串和带有最新时间戳的文件名:

find $Directory -type f -printf"%TY-%Tm-%Td-%TH-%TM-%TS %p

" | sed -r 's/([[:digit:]]{2})\.([[:digit:]]{2,})/\1-\2/' |     sort --field-separator='-' -nrk1 -nrk2 -nrk3 -nrk4 -nrk5 -nrk6 -nrk7 | head -n 1

生成窗体的输出:

这里有一个版本可以处理文件名,其中可能包含空格、换行符、全局字符:

find . -type f -printf"%T@ %p\0" | sort -zk1nr

find ... -printf打印文件修改(epoch值),后跟空格和\0终止的文件名。

sort -zk1nr读取nul终止的数据,并对其进行逆向排序。

因为问题是用Linux标记的,所以我假设gnu实用程序是可用的。

你可以在上面用管道输送:

xargs -0 printf"%s

"

打印由换行符终止的修改时间(最近的第一个)排序的修改时间和文件名。

对于普通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

您可以给printf命令find a try

%Ak File's last access time in

the format specified by k,

which is either @' or a directive for the Cstrftime'

function. The possible values for k are listed

below;

some of them might not be available on all

systems, due

to differences in `strftime' between systems.

这也可以通过bash中的reccursive函数来实现。

让f一个函数来显示文件的时间,该时间必须在字典中可排序,例如,yyyy-mm-dd等(取决于操作系统?)

F(){ stat --format %y"$1";}                # Linux

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

r在目录中运行的递归函数

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值