使用 Bash,我想查找任何指定目录及其子树的文件名、最后在该目录中创建的文件的创建日期和创建时间。例如,输出将是:
/home/dir filename0 creation_date0 creation_time0
/home/dir/subdir1 filename1 creation_date1 creation_time1
/home/dir/subdir2 filename2 creation_date2 creation_time2
答案1
尝试:
$ find /path/to/dir -type d -print0 | xargs -0 -I{} bash -c '
path="{}";
ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" | \
awk -v dir="$path" '\''BEGIN {found=0} ($1 ~ /-[rwx-]{9}/ && found == 0) {printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}'\'';'
使用制表符分隔的“absolute_path”、“filename”、“last_modif_date”、“last_modif_time”的示例输出:
/path/to/dir/otp_src_19.1/lib/ic/src icparse.erl 2016-09-20 21:56:21
/path/to/dir/otp_src_19.1/lib/dialyzer AUTHORS 2016-09-20 21:11:23
/path/to/dir/otp_src_19.1/lib/dialyzer/doc about.txt 2016-09-20 21:11:23
2 条评论:
- 上述解决方案基于最新的文件状态修改日期/时间,而不是基于最新的“出生”或“创建”日期/时间。要根据文件的创建日期/时间区分文件,您需要(扩展属性)在您的系统上启用。我假设您不这样做,因为它不是标准问题(POSIX),因此依赖此类元数据可能会导致可移植性问题。
如果您确实已xattr
启用,请编辑 OP 以使其清楚(并通知我),以便我可以更新此解决方案。 - 使用
zsh
shell 提出的解决方案可能比使用 更简单bash
。仅在bash
(zsh
与 with不同ls *(.)
)列表中常规文件withls
是不可能的,即没有这样的标志或选项或特殊的通配模式来执行以下操作:ls --regular-file-only
。因此,列出带有 的文件ls [options]
将产生常规文件、链接和目录,以及$PWD
.需要从中过滤掉常规文件。
怎么运行的:
find /path/to/dir -type d -print0
查找从 开始的目录子树中的所有目录/path/to/dir
。它打印每个目录,用 NULL 替换标准行尾字符,以避免目录名称中出现空格问题。这是通过管道输送到:xargs -0 -I{} bash -c '...'
从标准输入读取传入结果(这里标准输入被管道输入数据替换)并将它们呈现给以下迷你 Bash 脚本:ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" |
-AF
以长格式列出“几乎所有”( ) 文件,不带组 (-o
) 信息,也不考虑传递目录中的文件类型$path
,同时:- 格式化列出的文件输出 ( ),以便在下一步中可以轻松解析
--time-style=+"%Y-%m-%d %H:%M:%S"
其上次目录状态修改日期/时间 ( )。--time=ctime
请注意,文件的目录状态修改时间可能与该文件自身的修改时间不同。 - 根据文件显示的修改时间 (
-t
) 对文件进行排序,最新的位于最前面。 - 将格式化和排序的输出传输到以下
awk
过滤器中:
- 格式化列出的文件输出 ( ),以便在下一步中可以轻松解析
awk -v dir="$path" '...'
- 将 的值赋给
$path
内部awk
变量dir
BEGIN {found=0}
在块中将display-flag 设置found
为 0BEGIN
($1 ~ /-[rwx-]{9}/ && found == 0)
对于每条记录,测试该文件是否是常规文件,在这种情况下,记录的第一个字段 ($1
) 应符合正则表达式-[rwx-]{9}
,以及 (&&
) 对于给定目录 ( ),这种情况是否至少发生过一次,$path
在这种情况下,显示-flag (found
) 不再为零,并且跳过记录且不采取任何操作。{printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}
只要不跳过记录,即该文件是常规文件并且是$path
当前正在处理的目录( ) 中第一个显示的文件,该块就会执行。然后将显示标志 ( ) 设置为 1,以便不显示found
同一目录 ( ) 中的其他文件。$path
- 将 的值赋给
find
当你的目录树不小时,代码本质上依赖于主机,并且运行成本相当大。