这是一个非常简单的问题,一直困扰着我。一个小背景故事。我有一个充满脚本的文件夹。这些脚本获取数据文件*.dat
并在*.eps
中生成输出。我的脚本扩展名为*.plt
。我创建了一个单行shell脚本来运行该文件夹中的所有*.plt
文件。
#!/bin/sh
find . -name "*.plt" -exec {} \;
我只是想确保我在文档中使用的所有*.pdf
图片都是最新的。有一段时间,一行脚本很好。但是当文件数超过50时,运行需要一些时间。我很少更改数据文件,但经常更改*.plt
脚本。这些脚本的编写方式使得名为this_script_does_something.plt
的脚本将创建一个名为this_script_does_something.eps
的文件。
因此,这是我的问题。
*.plt
更新的*.eps
个文件?我知道我可以用Python做到这一点。但这似乎是在作弊。我也知道我可以寻找更新的*.eps
并执行比这更新的所有*.plt
。对于大多数实际案例,这将解决我的问题。我在输入问题时刚刚意识到这个选项,谢谢你SX。但是,作为一个教学练习,为了解决我原来的疑问,我想搜索个别情况:将每个*.plt
的修改时间与每个*.eps
进行比较,并仅在它们是比输出更新。可能吗?可以一行完成吗?
*.plt
脚本也应该在没有同音词*.eps
文件时执行,这通常意味着脚本是新的并且尚未执行。
答案 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}},bash
,ksh
或ksh93
支持zsh
)。例如,在Solaris 10上,您将使用:
-nt
编辑:
由于如果find . -name "*.eps" -exec ksh -c \
'plt=$(basename "$1" eps)plt; [ "$plt" -nt "$1" ] && $plt' ksh {} \;
文件不存在,脚本应该运行,该命令应该在.eps
文件上循环,例如:
.plt