递归地将目录的最后修改日期时间与内部最后修改文件的日期时间相同

递归地将目录的最后修改日期时间与内部最后修改文件的日期时间相同

以前,我使用此命令递归地对服务器上的dos2unix每个文件运行过:*.php

find . -name '*.php' -type f -exec dos2unix --keepdate {} +

处理的所有文件的dos2unix最后修改日期时间都完好无损,但包含此类文件的父目录的最后修改日期时间仍然更新为运行命令的时间。

如何使用一行代码递归地接触目录,将目录的最后修改日期时间设置为与目录内最后修改文件的日期时间相同?

由此:

dir_a/               2013-05-13 14:05
   abc.php           2012-09-01 12:34
   def.php           2012-09-15 23:45
   dir_b/            2013-05-13 14:05
       uvw.php       2012-10-01 01:23
       xyz.php       2012-10-08 09:10

对此:

dir_a/               2012-09-15 23:45
   abc.php           2012-09-01 12:34
   def.php           2012-09-15 23:45
   dir_b/            2012-10-08 09:10
       uvw.php       2012-10-01 01:23
       xyz.php       2012-10-08 09:10

服务器在 CentOS 5.6 上运行。

答案1

也许是这样的:

find . -type d -print0 | while read -r -d '' dir; do file="$(find "$dir" -maxdepth 1 -type f  -printf '%T+ %p\n' | sort -r | head -1 | cut -d' ' -f2-)";if [ -n "$file" ]; then touch "$dir" -mr "$file"; fi; done

解释:

要将修改日期从一个文件传递到另一个文件,我们必须运行:

touch file1 -mr file2

首先我们必须找到子目录:

find . -type d -print0 | while read -r -d '' dir; do echo "$dir"; done

在这种情况下,-exec选项会变得太复杂,所以我使用 while-read 方法。您需要确保使用管道输出find作为NUL记录分隔符,并告知read在该 ( ) 上进行拆分-d ''

要查找具有最后修改日期的文件,我可以使用:

find ./  -maxdepth 1 -type f  -printf '%T+ %p\n' | sort -r | head -1 | cut -d' ' -f2-

结合起来:

find . -mindepth 1  -type d -print0 | while read -r -d '' dir; do file="$(find "$dir" -maxdepth 1 -type f  -printf '%T+ %p\n' | sort -r | head -1 | cut -d' ' -f2-)";echo "$dir <- $file"; done

最后,添加触摸:

find . -mindepth 1  -type d -print0 | while read -r -d '' dir; do file="$(find "$dir" -maxdepth 1 -type f  -printf '%T+ %p\n' | sort -r | head -1 | cut -d' ' -f2-)";touch "$dir" -mr "$file"; done

-mindepth在这里使用选项,因为我从包含 dir_a 的目录启动了此命令,而该目录没有任何文件可从中读取日期。为了消除此问题,我可以使用 if-else 来确保我不会尝试从不存在的文件中读取时间:

find . -type d -print0 | while read -r -d '' dir; do file="$(find "$dir" -maxdepth 1 -type f  -printf '%T+ %p\n' | sort -r | head -1 | cut -d' ' -f2-)";if [ -n "$file" ]; then touch "$dir" -mr "$file"; fi; done

答案2

这应该可以做到:

find -mindepth 1 -type d -print0 | while IFS= read -r -d '' dir; do 
 time=$(
  find "$dir" -mindepth 1 -maxdepth 1 -type f -exec stat -c %Y {} \; | 
  sort -nk2 | tail -n 1
 ); touch -d @$time "$dir"; 
 done

解释:

  • find -mindepth 1 -type d | while IFS= read -r -d '' dir; do:遍历除当前目录之外的所有目录(-mindepth 1)。使用while循环IFS=-r标志是为了确保命令适用于包含空格或换行符(\n)或其他奇怪字符的目录名称。将-d ''分隔符设置为空字符,以便它可以与 find 的选项一起使用-print0

  • find $dir -mindepth 1 -maxdepth 1 -type f -exec stat --printf="%Y\n" {} \;:查找每个目录的所有文件$dir并运行stat,打印其修改日期自纪元以来的秒数

  • sort -nk2 | tail -n 1 :这只是对日期进行排序并保留最新的。最后两部分结合起来给出了保存在变量中的最新文件的修改时间$time

  • touch -d @$time $dir:这里我们使用touch命令来设置每个目录的修改时间。 是@告诉touch我们一个以秒为单位的时间,这是标准 GNU coreutils 功能

相关内容