我正在使用Bash编写脚本,其中我将在变量中获取文件名,然后使用该变量获取文件的Unix最后修改日期。
我需要获取此修改日期值,但无法使用stat命令。
您知道使用常见的*nix命令获取它的任何方法吗?
ls
:解析ls
是个坏主意。不仅某些文件名中的字符行为未定义且依赖于平台,而且在你的目的下,它会干扰六个月前的日期。简而言之,是的,在有限的测试中,它可能对你有效。它将不会是平台无关的(因此不具备可移植性),并且由于各种系统上“合法”文件名的范围,您的解析行为不能得到保证。 (例如,Ext4允许文件名中包含空格和换行符)。
尽管如此,就个人而言,我会使用ls
,因为它快速简单 ;)
正如评论中Hugo所指出的那样,OP不想使用stat
。此外,我应该指出以下部分是BSD-stat特定的(当我在Ubuntu上测试时,%Sm
标志无法工作;Linux有一个stat
命令,如果您对它感兴趣,请阅读man page)。
stat
解决方案:使用datedate
,至少在Linux上,具有一个标志:-r
,根据man page的说法:
显示文件的最后修改时间
因此,脚本化的解决方案类似于这样:
date -r ${MY_FILE_VARIABLE}
zsh% date -r MyFile.foo
Thu Feb 23 07:41:27 CST 2012
针对OP的评论:
如果可能,需要可配置日期格式
date
具有相当广泛的时间格式变量;请阅读man页面以获取更多信息。
我不确定date
在所有“类Unix系统”上的可移植性。对于基于BSD的系统(例如OS X),这将无法工作;BSD-date的-r
标志会执行完全不同的操作。问题没有明确规定需要多可移植的解决方案。对于基于BSD的解决方案,请参见下面的部分;)
使用stat
。您可以使用-f
标志格式化stat
的输出,并选择仅显示文件修改数据(对于此问题很好)。
例如,stat -f“%m%t%Sm%N” ./*
:
1340738054 Jun 26 21:14:14 2012 ./build
1340738921 Jun 26 21:28:41 2012 ./build.xml
1340738140 Jun 26 21:15:40 2012 ./lib
1340657124 Jun 25 22:45:24 2012 ./tests
这个命令的第一位是UNIX纪元时间,日期是文件修改时间,其余是文件名。
示例命令的分解
stat -f "%m%t%Sm %N" ./*
stat -f
:调用stat
并指定格式(-f
)。%m
:UNIX纪元时间。%t
:输出中的制表符分隔符。%Sm
:S
表示将输出显示为string
,m
表示使用文件修改数据。%N
:显示所讨论文件的名称。你的脚本中的一个命令如下:
stat -f "%Sm" ${FILE_VARIABLE}
将会给你输出,例如:
Jun 26 21:28:41 2012
stat
,因为他需要这个程序在任何类Unix操作系统上都能运行。 - WhyNotHugodate
在 BSD 操作系统上不可用(已在 OpenBSD 上测试)。而 stat
函数可以使用,但在 Linux 上可能会有问题。 - WhyNotHugols -l
不可移植,但date
更不可移植。问题在于BSD系统也使用-r
参数,但用于不同的目的。换句话说,使用-r
可能会得到一个有效的命令(退出状态=0),但却无法获得想要的结果。 - David W.date
在基于BSD的系统上不可移植。使用ls
不可移植因为它不能保证在任何平台上都能工作。这与date
和stat
形成对比,因为这两个工具的文档实现因平台而异 - 它们是不同的工具。ls
是相同的工具,对于合法输入具有未定义的行为。(虽然我个人会使用ls
...) 我不确定是否有一个好的、跨平台的解决方案来解决这种类型的问题。 - simontcurrent
是一个指向目录的符号链接,stat current
将会给出关于链接本身的信息,stat current/
将会给出关于链接目录的信息,但是date -f current
和date -f current/
都将会给出关于被链接的目录的信息,因此你无法通过使用date
来获取符号链接本身的时间。 - Jānis Elmeris有Perl吗?
perl -MFile::stat -e "print scalar localtime stat('FileName.txt')->mtime"
find $PATH -maxdepth 1 -name $FILE -printf %Tc
date +%Y-%m-%d -r /root/foo.txt
date +%H:%M -r /root/foo.txt
您可以使用 ls -l
命令列出最后修改时间,然后使用 cut
命令剪切出修改日期:
mod_date=$(ls -l $file_name | cut -c35-46)
这在我的系统上有效,因为日期出现在第35到46列之间。您可能需要在您的系统上进行调整。
日期有两种不同的格式:
Mmm dd hh:mm
Mmm dd yyyy
超过一年前修改的文件将具有后一种格式。少于一年前修改的文件将具有第一种格式。您可以搜索“:”并知道文件所处的格式:
if echo "$mod_date" | grep -q ":"
then
echo "File was modified within the year"
else
echo "File was modified more than a year ago"
fi
ls
通常被认为是不良实践。虽然它(可能)可以正常工作,但不能保证其可移植性或健壮性。 - simontls
之外,没有太多选择了。正如我在帖子中所述,它可能在 OP 的系统上不完全相同。 - David W.
stat
? - Sean Brightdate
不支持-r
标志),能否提供更具体的平台信息 - 您已经标记了Linux
和Unix
;stat
和date
在我遇到的各种 Linux 发行版中都非常普遍(据我所知)。 - simont