查找比具有相似名称但扩展名不同的文件更新的文件

时间:2014-12-23 00:02:10

标签: shell find file-comparison

这是一个非常简单的问题,一直困扰着我。一个小背景故事。我有一个充满脚本的文件夹。这些脚本获取数据文件*.dat并在*.eps中生成输出。我的脚本扩展名为*.plt。我创建了一个单行shell脚本来运行该文件夹中的所有*.plt文件。

#!/bin/sh
find . -name "*.plt" -exec {} \;

我只是想确保我在文档中使用的所有*.pdf图片都是最新的。有一段时间,一行脚本很好。但是当文件数超过50时,运行需要一些时间。我很少更改数据文件,但经常更改*.plt脚本。这些脚本的编写方式使得名为this_script_does_something.plt的脚本将创建一个名为this_script_does_something.eps的文件。

因此,这是我的问题。

  • 是否有办法编写一个精炼的shell脚本,该脚本只执行比类似名称*.plt更新的*.eps个文件?

我知道我可以用Python做到这一点。但这似乎是在作弊。我也知道我可以寻找更新的*.eps并执行比这更新的所有*.plt。对于大多数实际案例,这将解决我的问题。我在输入问题时刚刚意识到这个选项,谢谢你SX。但是,作为一个教学练习,为了解决我原来的疑问,我想搜索个别情况:将每个*.plt的修改时间与每个*.eps进行比较,并仅在它们是比输出更新。可能吗?可以一行完成吗?

编辑:我忘了添加,*.plt脚本也应该在没有同音词*.eps文件时执行,这通常意味着脚本是新的并且尚未执行。

2 个答案:

答案 0 :(得分:1)

我想我正在使用:

#!/bin/bash

for plt in *.plt
do
    eps=$(basename "$plt" .plt).eps
    if [ "$plt" -nt "$eps" ]
    then "$plt"
    fi
done

这使用Bash / Korn shell运算符-nt比'更新。 (以及#39;年龄超过')的反向-ot运算符。我假设这些文件都在一个目录中,因此不需要进行递归搜索。如果这不正确,请使用单独的:

find . -type d -exec sh -c "cd {}; new-script.sh" \;

(其中new-script.sh是我刚刚展示的脚本)。或者使用Bash扩展程序**运算符:

for plt in *.plt **/*.plt

您可能需要设置Bash nullglob选项:

shopt -s nullglob

当扩展与任何文件都不匹配时,这不会生成任何内容。


还在.eps文件不存在时生成:

#!/bin/bash

for plt in *.plt
do
    eps=$(basename "$plt" .plt).eps
    if [ ! -f "$eps" ] || [ "$plt" -nt "$eps" ]
    then "$plt"
    fi
done

唯一不完全通用的shell功能是-nt运算符。如果您的/bin/sh不支持,请检查/bin/[命令 - 它可能 - 或在shebang行中使用Korn Shell或Bash而不是/bin/sh

答案 1 :(得分:1)

此脚本应该按预期执行:

find . -name "*.eps" -exec sh -c \
     'plt=$(basename "$1" eps)plt; [ "$plt" -nt "$1" ] && $plt' sh {} \;

它会递归到子目录中,如果有的话。如果你不想这样,并且你使用GNU find,一个简单的解决方法是运行:

find . -maxdepth 1 -name "*.eps" -exec sh -c \
     'plt=$(basename "$1" eps)plt; [ "$plt" -nt "$1" ] && $plt' sh {} \;

如果您不使用GNU查找,则可以使用该语法:

find *.eps -type f -exec sh -c \
     'plt=$(basename "$1" eps)plt; [ "$plt" -nt "$1" ] && $plt' sh {} \;

但是后者可能会失败并且" arg列表太长"如果您有大量符合*.eps模式的文件,则会出错。基于for file in *.extension循环的任何解决方案都会遇到同样的问题。

另请注意,POSIX未指定-nt,因此根据您的系统,您可能希望明确说明要使用的shell而不是sh(主流shell,如dash,{ {1}},bashkshksh93支持zsh)。例如,在Solaris 10上,您将使用:

-nt

编辑:

由于如果find . -name "*.eps" -exec ksh -c \ 'plt=$(basename "$1" eps)plt; [ "$plt" -nt "$1" ] && $plt' ksh {} \; 文件不存在,脚本应该运行,该命令应该在.eps文件上循环,例如:

.plt
相关问题