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

时间:2010-08-24 21:48:32

标签: bash file shell grep conditional

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

我需要: 1.)检查是否存在与模式匹配的某些文件 和 2.)检查不同文件中的文本是否存在。

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

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

类似

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

虽然奇怪但是失败了:

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

都通过......

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

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

3 个答案:

答案 0 :(得分:11)

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

if [ `grep -q …` ]; 

这会在反引号之间运行grep命令,并在条件命令内插入输出。由于grep -q不会产生任何输出,因此就好像你写了if [ ];

一样

条件应该测试grep的返回码,而不是它的输出。因此,它应该简单地写成

if grep -q …;

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

if [ "$(find …)" != "" ];

(等效测试为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更合理。

  3. 全部放在一起:

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

答案 1 :(得分:0)

bash 4

shopt -s globstar
files=$(echo **/jobscript_minim*cmd*o*)
if grep -q "pattern" file && [[ ! -z $files ]];then echo "passed"; fi

答案 2 :(得分:0)

for i in filename*; do FOUND=$i;break;done
if [ $FOUND == 'filename*' ]; then
echo “No files found matching wildcard.”
else
echo “Files found matching wildcard.”
fi