Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/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
Shell 多个表达式是否可以找到合适的工具?_Shell_Unix_Find - Fatal编程技术网

Shell 多个表达式是否可以找到合适的工具?

Shell 多个表达式是否可以找到合适的工具?,shell,unix,find,Shell,Unix,Find,我有很多目录,其中包含一组程序的输出和数据文件。每个目录都有相似的内容,我的go还有4个级别。我的目标是识别所有目录,这些目录在任何子目录中都有核心文件,并且具有大于1k的给定名称模式的日志文件。日志文件与核心文件不在同一个子目录中 我可以独立地编写用于每个目标的find命令,但我所有的组合表达式的尝试都无法产生任何结果 第一命令: find \( \( -path "./SESS*" -name "log_snap_*" \) \( -size +1k\) \) 第二命令: find \(

我有很多目录,其中包含一组程序的输出和数据文件。每个目录都有相似的内容,我的go还有4个级别。我的目标是识别所有目录,这些目录在任何子目录中都有核心文件,并且具有大于1k的给定名称模式的日志文件。日志文件与核心文件不在同一个子目录中

我可以独立地编写用于每个目标的find命令,但我所有的组合表达式的尝试都无法产生任何结果

第一命令:

find \( \( -path "./SESS*" -name "log_snap_*" \) \( -size +1k\) \)
第二命令:

find \( -path "./SESS" -regex "*core.[0-9]+\(.gz)*" \)

如何编写一个测试来识别满足这两个标准的目录?

对这个问题有多种合理的解释——请参阅下面基于不同答案的答案


假设你指的是“任一”标准。。。 请考虑以下设置:

files_empty=(
  SESS/log_snap_1234  # ignored because not more than 1k in size
  SESS/ignoreme       # ignored because not matching either pattern 
  SESS/core.13.gz     # expected to be in results
  SESS/core.13        # expected to be in results
)
files_full=(
  SESS/log_snap_2345  # expected to be in results
)

{ tempdir=$(mktemp -d /tmp/test.XXXXXX) && cd "$tempdir"; } || exit
mkdir -p SESS bad
touch "${files_empty[@]}"
for f in "${files_full[@]}"; do
  dd if=/dev/zero of="$f" bs=1k count=2
done
如果在使用上述方法创建测试环境后,我们在GNU
find
中运行以下操作:

find ./SESS \
   '(' '(' -name 'log_snap_*' -size +1k ')' \
    -o '(' -regextype posix-extended -regex ".*core[.][0-9]+([.]gz)?" ')' \
   ')' -print
…我们得到了正确的结果:

./SESS/log_snap_2345
./SESS/core.13
./SESS/core.13.gz

那么,发生了什么变化

  • 当您只需修改起始位置时,不要使用
    -path
    过滤正在搜索的位置。当您运行
    find时-路径“/SESS/*”
    ,它在
    下搜索所有地方,但当结果与
    /SESS/*
    不匹配时就会丢弃;与只搜索您首先关心的目录相比,这是非常低效的
  • 使用
    -o
    指定或条件
  • 当您想要的是后续测试之间的AND时,分组运算符或显式的
    -a
    没有意义,因为这是隐式行为
  • 明确指定最终操作(例如
    -print
    )是一种非常好的形式。在您当前的情况下不是完全强制的,但在其他常见场景中是强制的(例如使用
    -prune
    );因此,养成习惯可以减少犯错的空间
  • 不允许正则表达式以
    *
    开头,因为
    *
    表示“前面的项为零或多个”。在正则表达式的开头,没有优先项,因此此构造没有任何意义
  • 在正则表达式中,显式句点应写为
    [.]
    ,因为裸
    表示“任意字符之一”

如果你真的是指“两者”标准。。。 对于这个部分,我们实际上不需要进入
find
。一个警告:我有意避免正确处理文件名包含文字换行符的情况。这是可能发生的。忽视它并不理想

无论如何,将两个shell函数作为两个不同的
find
命令输出的替代:

find1_cmd() {
  printf '%s\n' \
    SESS/session_one/log_snap_1234 \
    SESS/session_one/log_snap_4567 \
    SESS/session_three/log_snap_8901
}

find2_cmd() {
  printf '%s\n' \
    SESS/session_one/core.1234.gz
    SESS/session_four/core.5678.gz
}
我们只能在这两个目录中找到目录,如下所示:

prep() {
  while IFS= read -r line; do
    printf '%s\n' "${line%/*}"  # remove the filename, leaving only the directory
  done | sort -u                # sort and uniq-ify the results
}

comm -12 <(find1_cmd | prep) <(find2_cmd | prep)
prep(){
当IFS=读取-r行时;执行
printf'%s\n'${line%/*}删除文件名,只保留目录
完成|排序-u#排序并统一结果
}

comm-12为什么所有嵌套的组都是?您只需要条件and,对吗?就这点而言,为什么
find-path./SESS
而不是
find./SESS
?后者的效率要高得多,因为它不会在只考虑每个结果的分支上递归。而且,
-regex“*core。[0-9]+\(.gz)*”
实际上不是有效的regex。不能将
*
作为正则表达式中的第一个字符,因为它表示“前一项的零个或多个”;在第一个位置,没有前面的项目。请参阅我的答案,了解问题的结构——显示创建测试环境的代码,然后显示给定该测试环境的预期输出,然后显示给定该测试环境的实际输出。定义进一步讨论了这一点……如果您提供了这样的代码——进行设置,并给我们预期的/预期的输出——那么您的预期逻辑将不会有任何猜测或解释。是的,我确实需要所有标准的and,而不是or。我想确定具有核心文件和某些特定大小的日志文件的顶级会话_xxxx目录。