grep 别名可以安全地忽略多个目录

grep 别名可以安全地忽略多个目录

日常使用情况是:

grep -rIn pattern directory

有一些文件我想避免,它们位于有时具有这种路径的目录中:app/lib/bower/lodash, app/lib/bower/paho-mqtt-js, app/lib/bower/socket-io-client.

理想的解决方案是在路径中进行检测app/lib/bower/,但这很难。是否可以?

我想出了:

alias grep='grep --exclude-dir={lodash,paho-mqtt-js,socket-io-client}'

足够好(尽管添加新东西时需要维护)。如果目录被 grep 排除,如何至少在 stderr 中添加一个简短的警告?

答案1

我会用find

mygrep() (
  pattern=$1; shift
  find "$@" -type d -path '*/app/lib/bower' -exec sh -c '
    printf >&2 "Warning: ignoring \"%s\" directory\n" "$@"
    ' sh {} + -prune -o -type f -exec grep -IHne "$pattern" {} +
)

-I并且-H是 GNU 扩展)。

用于:

mygrep pattern dir1 dir2

(确保dir1anddir2看起来不像find谓词)。

-exec sh...+如果您不关心这些警告消息,请删除。

当你如此显着地改变它的行为时,使用它grep作为你的别名是一个坏主意。

如果您需要将选项传递给grep,您可以使用GREP_OPTIONS如下变量:

GREP_OPTIONS=-i mygrep foo dir

但请注意,对该选项的支持将在 的未来版本中删除grep,因此更好的选择可能是提供一种方法,mygrep将选项传递grep给专用数组(如果您的 shell 支持它们):

mygrep() (
  pattern=$1; shift
  find "$@" -type d -path '*/app/lib/bower' -exec sh -c '
    printf >&2 "Warning: ignoring \"%s\" directory\n" "$@"
    ' sh {} + -prune -o -type f -exec \
    grep -IHne "${g[@]}" "$pattern" {} +
)

g=(-i --exclude-dir=.git); mygrep foo dir1 dir2

或者用来--告诉mygrep选项停止的位置:

mygrep() (
  grep_options=()
  for i do
    grep_options+=("$i")
    shift
    [ "$i" != "--" ] || break
  done
  pattern=${1?need a pattern}; shift
  find "$@" -type d -path '*/app/lib/bower' -exec sh -c '
    printf >&2 "Warning: ignoring \"%s\" directory\n" "$@"
    ' sh {} + -prune -o -type f -exec \
    grep -H "${grep_options[@]}" "$pattern" {} +
)

mygrep -nI --exclude-dir=.git -- pattern dir1 dir2

(并确保您不--作为选项参数传递,就像您想排除文件一样--,请使用--exclude=--,而不是--exclude --例如。这也排除了像mygrep -e pattern1 -e pattern2 -- dir或 之类的用法mygrep -f patternfile -- dir)。

相关内容