Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash复合条件,带有通配符和文件存在性检查_Bash_File_Shell_Grep_Conditional - Fatal编程技术网

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

Bash复合条件,带有通配符和文件存在性检查,bash,file,shell,grep,conditional,Bash,File,Shell,Grep,Conditional,我已经掌握了Bash复合条件的基本知识,并且已经阅读了一些检查通配符文件是否存在的不同方法,但是这一种方法让我无法理解,所以我想我应该寻求帮助 我需要: 1.)检查是否存在与模式匹配的文件 及 2.)检查其他文件中是否存在文本 我知道有很多方法可以做到这一点,但我真的没有知识来区分它们的优先级(如果你有这些知识,我也会有兴趣阅读) 首先想到的是使用find for#1和grep for#2 大概是 if [ `grep -q "OUTPUT FILE AT STEP 1000" ../log/m

我已经掌握了Bash复合条件的基本知识,并且已经阅读了一些检查通配符文件是否存在的不同方法,但是这一种方法让我无法理解,所以我想我应该寻求帮助

我需要: 1.)检查是否存在与模式匹配的文件 及 2.)检查其他文件中是否存在文本

我知道有很多方法可以做到这一点,但我真的没有知识来区分它们的优先级(如果你有这些知识,我也会有兴趣阅读)

首先想到的是使用find for#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语句中多个文件名匹配通配符的问题。最好的解决办法是什么?(在回答我的问题时,我假设你在这个过程中也会尝试一下这个问题)


有什么想法/解决方案/建议吗?

让我们先来看看您的尝试失败的原因:

if [ `grep -q …` ]; 
这将在反勾号之间运行
grep
命令,并在条件命令内插入输出。由于
grep-q
不产生任何输出,就好像您编写了
if[]

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

if grep -q …;
find
命令即使没有找到任何内容,也会返回0(即true),因此此技术不起作用。通过收集其输出并将其与空字符串进行比较,测试其输出是否为空:

if [ "$(find …)" != "" ];
(如果[-n”$(查找…)]
,则等效测试为

注意这里的两件事:

  • 我使用了
    $(…)
    而不是反勾号。它们是等价的,只是backticks需要在它们内部进行奇怪的引用(特别是当您试图嵌套它们时),而
    $(…)
    是简单可靠的。只需使用
    $(…)
    并忘记反勾号(除了需要在双引号内写入
    \`

  • $(…)
    周围有双引号。这真的很重要。如果没有引号,shell将把
    find
    命令的输出分解为单词。如果
    find
    打印,比如说,两行
    dir/file
    dir/otherfile
    ,我们需要
    If[“dir/file dir/otherfile”=“”]待执行,而不是
    如果[dir/file dir/otherfile=”“]这是一个语法错误。这是shell编程的一般规则:始终在变量或命令替换前后加上双引号。(变量替换是
    $foo
    ${foo}
    ;命令替换是
    $(command)


现在让我们看看您的要求

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

    如果您递归地在当前目录或其下的任何目录中查找文件,则
    find-name“PATTERN”
    是正确的。然而,如果目录树变大,它的效率就会降低,因为当我们只关心一个匹配项时,它会花费大量时间打印所有匹配项。一种简单的优化方法是,通过管道将第一条管线插入
    头部-n1
    find
    一旦意识到
    head
    对它要说的内容不再感兴趣,就会停止搜索

    如果[“$(查找-名称“jobscript_minimicmdo”| head-n 1)!=”

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

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

    如果[“$(find-maxdepth 1-name“jobscript_minim*cmd*o*”)!=”

    还有其他更具可移植性的解决方案,但编写起来更复杂

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

    您已经获得了正确的
    grep
    命令。请注意,如果要搜索文字字符串,应使用
    grep-F
    ;如果您正在寻找一个regexp,
    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
    
    bash 4


    请添加一些解释性文字。
    shopt -s globstar
    files=$(echo **/jobscript_minim*cmd*o*)
    if grep -q "pattern" file && [[ ! -z $files ]];then echo "passed"; fi
    
    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