Bash复合条件,带通配符和文件存在性检查

Jas*_*ick 5 bash shell conditional grep file

我已经掌握了Bash复合条件的基础知识,并且已经阅读了几种不同的方法来检查文件是否存在通配符文件,但是这个方法让我望而却步,所以我想我会请求帮助......

我需要:1)检查一些文件匹配模式的存在和2)检查文本在不同的文件存在.

我知道有很多方法可以做到这一点,但我并没有真正的知识来优先考虑它们(如果你有这方面的知识,我也有兴趣阅读它).

首先想到的是使用#1的#和#2的grep

所以像

if [ `grep -q "OUTPUT FILE AT STEP 1000" ../log/minimize.log` ] \
      && [ `find -name "jobscript_minim\*cmd\*o\*"` ]; then
   echo "Both passed! (1)"
fi
Run Code Online (Sandbox Code Playgroud)

虽然好奇但是失败了:

if `grep -q "OUTPUT FILE AT STEP 1000" ../log/minimize.log` ;then
   echo "Text passed!"
fi
if `find -name "jobscript_minim\*cmd\*o\*"` ;then
   echo "File passed!"
fi
Run Code Online (Sandbox Code Playgroud)

都通过......

我已经做了一些阅读,并且看到人们在if语句中讨论了匹配通配符的多个文件名的问题.什么是最好的解决方案?(在回答我的问题时,我假设你在这个过程中对这个问题采取了一个解决方案)

任何想法/解决方案/建议?

Gil*_*il' 11

让我们先解决你的尝试失败的原因:

if [ `grep -q …` ]; 
Run Code Online (Sandbox Code Playgroud)

这将grep在反引号之间运行命令,并在条件命令内插入输出.既然grep -q没有产生任何输出,那就好像你写的那样if [ ];

条件应该测试返回代码grep,而不是测量其输出.因此,应该简单地写成

if grep -q …;
Run Code Online (Sandbox Code Playgroud)

find命令返回0(即true),即使它什么都没找到,所以这种技术不起作用.什么工作是测试它的输出是否为空,通过收集它的输出任何比较它与空字符串:

if [ "$(find …)" != "" ];
Run Code Online (Sandbox Code Playgroud)

(等效测试是if [ -n "$(find …)" ].)

请注意两件事:

  • 我用$(…)而不是反叛.它们是等效的,除了反引号需要在它们内部引用奇怪的引用(特别是如果你试图嵌套它们),而$(…)简单可靠.只是使用$(…)并忘记反引号(除了你需要\`在双引号内写).

  • 周围有双引号$(…).这非常重要.如果没有引号,shell会将find命令的输出分解为单词.如果find打印,说,两行dir/filedir/otherfile,我们要if [ "dir/file dir/otherfile" = "" ];执行,不if [ dir/file dir/otherfile = "" ];这是一个语法错误.这是shell编程的一般规则:总是在变量或命令替换周围加上双引号.(变量替换是$foo${foo};命令替换是$(command).)


现在让我们看看你的要求.

  1. 检查是否存在与模式匹配的文件

    如果您正在寻找当前目录中的文件或递归下面的任何目录中的文件,那么这find -name "PATTERN"是正确的.但是,如果目录树可能变得很大,那么效率很低,因为当我们只关心一个匹配时,它会花费大量时间打印所有匹配.一个简单的优化是只通过管道保留第一条线head -n 1; find一旦意识到head不再对它所说的内容感兴趣,它就会停止搜索.

    if ["$(find -name"jobscript_minim cmd o"| head -n 1)"!=""];

    (请注意,双引号已经保护通配符不受扩展.)

    如果您只是在当前目录中查找文件,假设您有GNU查找(Linux,Cygwin和Gnuwin32就是这种情况),一个简单的解决方案就是告诉它不要比当前目录更深入.

    if ["$(find -maxdepth 1 -name"jobscript_minim*cmd*o*")"!=""];

    还有其他更便携的解决方案,但写入起来更复杂.

  2. 检查其他文件中是否存在文本.

    你已经有了正确的grep命令.请注意,如果要搜索文字字符串,则应使用grep -F; 如果你正在寻找一个正则表达式,grep -E有一个比普通的更健全的语法grep.

把它们放在一起:

if grep -q -F "OUTPUT FILE AT STEP 1000" ../log/minimize.log &&
   [ "$(find -name "jobscript_minim*cmd*o*")" != "" ]; then
  echo "Both passed! (1)"
fi
Run Code Online (Sandbox Code Playgroud)