Unix命令查找最近创建的目录

10

我想要复制最近创建的目录中的文件。在 Unix 中该如何实现?

例如,如果我的目录名称是日期时间戳:

/20110311
/20110318
/20110325

Unix系统中不存储创建时间,您只能使用最后修改时间作为替代。 - Tom Zych
最后修改时间是我想要的文件夹信息。我怎么获取这个信息?我需要使用 find 命令吗? - jdamae
每当一个文件被添加到目录中,该目录的最后修改时间就会更新。这样可以吗? - Julius Musseau
你的目录是否总是按照YYYYMMDD日期模式命名的?因为这会使解决方案更容易。:-) 不过,如果在同一天创建了多个目录,你不确定该如何应对! - Julius Musseau
@Juilus - 是的,我正在使用YYYYMMDD日期作为我的模式。 - jdamae
8个回答

10

我认为你在询问的问题的答案就是这个。

当我处理许多带有日期/时间戳的目录时,我总是采用你提到的方法,即 YYYYMMDD - 这么做的好处是日期顺序也是字母顺序。在大多数 shell(肯定包括 bash,其他的我90%确定)中,“*” 的展开是按字母顺序完成的,而默认情况下 'ls' 返回的也是字母顺序。因此

    ls | head -1
    ls | tail -1

给出目录中最早和最晚的日期。

可以扩展为仅保留最后5个条目等。


那基本上就是我需要的。谢谢! - jdamae
实际上,如果我需要最新创建的前2-3个目录,这对我来说非常有效。ls | tail -2 - jdamae

6
lastdir=`ls -tr <parentdir> | tail -1`

我不知道如何让反引号与这里的评论系统兼容。只需将那些单引号替换为反引号即可。


4
在 bash 中,你可以使用 $(...) 来代替反引号。 - Tom Zych

3
在一些实验后,我得出了以下结论:
Unix中的stat命令在这里非常有用。'-t'选项使stat以简洁模式(所有信息都在一行内)打印其输出,而该简洁输出的第13个元素是最后修改时间的Unix时间戳(自纪元以来的秒数)。此命令将按从最新到最旧的顺序列出所有目录(和子目录)。
find -type d -exec stat -t {} \; | sort -r -n -k 13,13

希望 stat 的“简洁”模式在未来版本中保持一致!
以下是使用的命令行选项的一些解释:
find -type d                # only find directories
find -exec [command] {} \;  # execute given command against each *found* file.
sort -r                     # reverse the sort
sort -n                     # numeric sort (100 should not appear before 2!)
sort -k M,N                 # only sort the line using elements M through N.

回到您最初的请求,要复制文件,可以尝试以下方法。要输出仅一个目录(即最新的),请将此附加到命令中(注意初始管道符),并使用反引号将所有内容馈入您的“cp”命令以执行复制。

| head --lines=1 | sed 's/\ .*$//'

谢谢您的建议。非常有趣。您能编辑一下,让我看到整个命令吗?我不确定我是否正确地尝试了这个。再次感谢。 - jdamae

3
ls基于的解决方案的问题在于它们不能仅过滤目录。我认为这个命令可以解决这个问题:
cp `find . -mindepth 1 -maxdepth 1 -type d  -exec stat -c "%Y %n" {} \;  |sort -n -r |head -1 |awk '{print $2}'`/* /target-directory/.

这可能会有所帮助,但请注意,这只会复制直接目录中的文件。如果您想要将最新目录下的任何内容复制到新目录中,我认为最好使用rsync:

rsync -av `find . -mindepth 1 -maxdepth 1 -type d  -exec stat -c "%Y %n" {} \;  |sort -n -r |head -1 |awk '{print $2}'`/ /target-directory/ 

但这取决于您想要的行为。反引号中的内容解释如下:

  • . - 当前目录(您可能希望在此处指定绝对路径)
  • -mindepth/-maxdepth - 仅将find命令限制在当前目录的直接子级上
  • -type d - 仅限目录
  • -exec stat .. - 输出来自find的修改时间和目录名称
  • sort -n -r |head -1 | awk '{print $2}' - 按日期排序目录并输出最近修改的名称

2
如果您的目录按照问题所示的 YYYYMMDD 命名,请利用字母排序的通配符。
将所有目录放入一个数组中,然后选择第一个目录
dirs=(*/); first_dir="$dirs";

这实际上是一个快捷方式,相当于first_dir="${dirs[0]}";
同样地,对于最后一个
dirs=(*/); last_dir="${dirs[$((${#dirs[@]} - 1))]}";

丑陋的语法,但这就是它的含义:
# Create an array of all directories inside the working directory.
dirs=(*/);

# Get the number of entries in the array.
num_dirs=${#dirs[@]};

# Calculate the index of the last entry.
last_index=$(($num_dirs - 1));

# Get the value at the last index.
last_dir="${dirs[$last_index]}";

我知道这是一个有已接受答案的老问题,但我认为这种方法更可取,因为它完全在Bash中完成。没有理由生成额外的进程,更不用说解析ls的输出了。(尽管,在这种特定情况下使用YYYYMMDD名称应该没问题。)

supertrue:在Bash中不行,至少我不知道。你是在普通的Bourne shell sh中尝试吗? - janmoesen
不,我使用Bash(Mac终端),我只是想知道它的含义是什么,因为#也用于注释。 - supertrue
1
啊,我明白了。当它在带大括号的变量内部时,它具有特殊含义。${#foo} 计算名为 foo 的普通(字符串)变量中字符的数量,${foo[@]} 计算名为 foo 的数组中元素的数量。请参阅 Bash 参数扩展 - janmoesen

0
find ~ -type d | ls -ltra

这是我最近学到的一个简单而有用的命令。 该命令将以相反的时间顺序显示结果。


1
ls命令不接受管道符 - Ryan Ward Valverde

0
请尝试以下命令:
ls -1tr | tail -1


-1

我写了一个命令,可以用来识别哪个文件夹或文件是作为最新创建的。这似乎很纯粹 :)

#/bin/sh
path=/var/folder_name

newest=`find $path -maxdepth 1 -exec stat -t {} \; |sed 1d |sort -r -k 14 | head -1 |awk {'print $1'} | sed 's/\.\///g'`

find $path -maxdepth 1| sed 1d |grep -v $newest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接