【问题标题】:filename last modification date shell in script文件名最后修改日期脚本中的shell
【发布时间】:2012-06-26 17:18:50
【问题描述】:

我正在使用 bash 构建一个脚本,其中我将在变量中获取文件名,然后使用此变量获取文件 unix 上次修改日期。

我需要获取这个修改日期值,我不能使用 stat 命令。

你知道用常用的 *nix 命令获取它的任何方法吗?

【问题讨论】:

  • 如果可能,使用可配置的日期格式。
  • 为什么不能使用stat
  • stat 在我当前工作的环境中不可用。
  • 如果我的回答不起作用(date 不支持 -r 标志),您能否提供更具体的平台信息 - 您已用 LinuxUnix 标记; statdate(据我所知)在我遇到的各种 Linux 发行版中都非常普遍。
  • 我需要一个可移植或强大的解决方案,我在一个 HP-UX 系统中,这个脚本也应该在 Linux 中运行。也没有 perl。

标签: linux bash shell unix hp-ux


【解决方案1】:

为什么你不应该使用ls

解析ls is a bad idea。不仅文件名中某些字符的行为未定义和平台相关,为了您的目的,它会mess with dates when they're six months in the past。简而言之,是的,它可能会在您有限的测试中为您工作。它将独立于平台(因此没有可移植性),并且鉴于各种系统上的“合法”文件名范围,您的解析行为得到保证。 (Ext4,例如allows spaces and newlines in filenames)。

说了这么多,就我个人而言,我会使用ls,因为它既快速又简单;)

编辑

正如 Hugo 在 cmets 中指出的那样,OP 不想使用 stat。此外,我应该指出,以下部分是 BSD-stat 特定的(当我在 Ubuntu 上测试时,%Sm 标志不起作用;Linux 有一个 stat 命令,如果您对此感兴趣,请阅读 @ 987654324@)。

所以,一个非stat 的解决方案:使用日期

date,至少在Linux上,有一个标志:-r,根据man page

显示文件的最后修改时间

因此,脚本化解决方案类似于:

date -r ${MY_FILE_VARIABLE}

这会返回类似这样的东西:

zsh% date -r MyFile.foo
Thu Feb 23 07:41:27 CST 2012

解决 OP 的评论:

如果可能的话,使用可配置的日期格式

date 有一组相当广泛的时间格式变量;阅读手册页以获取更多信息。

我不能 100% 确定 date 在所有“类 UNIX 系统”中的可移植性。对于基于 BSD 的(例如 OS X),这将工作; BSD-date 的 -r 标志做了完全不同的事情。这个问题并没有具体说明解决方案的便携性。对于基于 BSD 的解决方案,请参阅下面的部分 ;)

更好的解决方案,BSD 系统(在 OS X 上测试,使用 BSD-stat;GNU stat 略有不同,但可以以相同的方式工作)。

使用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 epoch time,日期是文件修改时间,其余的是文件名。

示例命令分解

stat -f "%m%t%Sm %N" ./*

  1. stat -f:调用stat,并指定格式(-f)。
  2. %m:UNIX 纪元时间。
  3. %t:输出中的制表符分隔符。
  4. %SmS 表示将输出显示为stringm 表示使用文件修改数据。
  5. %N:显示有问题的文件名。

脚本中的命令如下:

stat -f "%Sm" ${FILE_VARIABLE}

会给你输出如:

Jun 26 21:28:41 2012

阅读man pagestat了解更多信息;时间戳格式化由strftime 完成。

【讨论】:

  • 我会为“不要使用 ls”部分投票给你,但操作 确实 说他不能使用 stat,因为他需要这样做可移植到任何类 Unix 操作系统。
  • date 在 BSD 上不起作用(在 OpenBSD 上测试)。 stat 可以,但不能在 linux 上运行。
  • @Hugo 是的。如答案中所述; date 不能移植到 BSD 系统,这就是为什么我在答案中留下了 stat 部分。我不确定是否有便携式解决方案;包含find 的答案也不能移植到我的 BSD 系统中。
  • 您抱怨ls -l 不便携,但date 更不便携。问题是 BSD 系统也使用 -r 参数,但目的不同。换句话说,使用-r 最终可能是一个有效的命令(退出状态= 0),但不会得到你想要的结果。
  • @DavidW。答案提到date 不能移植到基于 BSD 的系统。使用ls 是不可移植的因为它不能保证在任何 平台上工作。这与不可移植的datestat 形成鲜明对比,因为工具的文档化 实现因平台而异——它们是不同的工具。 lssame 工具,具有未定义的合法输入行为。 (我个人确实说过我会使用ls,不过......)我不相信有一个很好的跨平台解决方案来解决这类问题。
【解决方案2】:

有 perl 吗?

perl -MFile::stat -e "print scalar localtime stat('FileName.txt')->mtime"

【讨论】:

    【解决方案3】:

    怎么样:

    find $PATH -maxdepth 1 -name $FILE -printf %Tc
    

    请参阅 find 手册页,了解可用于 %T 的其他值。

    【讨论】:

      【解决方案4】:

      您可以使用“日期”命令添加所需的格式选项格式:

       date +%Y-%m-%d -r /root/foo.txt
      

      2013-05-27

       date +%H:%M -r /root/foo.txt
      

      23:02

      【讨论】:

        【解决方案5】:

        您可以使用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
        

        【讨论】:

        • 解析lsgenerally considered bad practise。虽然它(可能)工作正常,但不能保证,不能被认为是便携或健壮的。
        • @simont 解决方案呢?您应该使用通用的 shell 脚本和或多或少的标准工具,我认为这意味着您也不能使用像 Perl 或 Python 这样的脚本语言。您也不能使用统计数据。有了这些限制,除了解析ls 之外,剩下的不多了。正如我在帖子中所说,它在 OP 系统上的工作方式可能不完全相同。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-13
        • 2011-11-25
        • 1970-01-01
        • 2019-11-06
        • 2016-01-20
        • 2020-05-12
        • 2019-02-26
        相关资源
        最近更新 更多