Regex 在所有情况下忽略子目录(相对、绝对…)

Regex 在所有情况下忽略子目录(相对、绝对…),regex,bash,path,find,realpath,Regex,Bash,Path,Find,Realpath,我想使用find跳过子目录$skip 遗憾的是,这一基本命令并非在所有情况下都有效: find $DIR -path $SKIP -prune -o print 请帮助我改进脚本skipit.sh: #!/bin/bash SKIP=$1 shift find "${@:-.}" -path "$SKIP" -prune -o -print 基本例子 该示例基于以下目录树: dir ├── skip ├── a └── b 好: 失败: 失败: 使用-regex 好: 好: 失败: 我的查

我想使用
find
跳过子目录
$skip

遗憾的是,这一基本命令并非在所有情况下都有效:

find $DIR -path $SKIP -prune -o print
请帮助我改进脚本
skipit.sh

#!/bin/bash
SKIP=$1
shift
find "${@:-.}" -path "$SKIP" -prune -o -print
基本例子 该示例基于以下目录树:

dir
├── skip
├── a
└── b
好:

失败:

失败:

使用
-regex
好:

好:

失败:

我的
查找
版本 只有在以下示例中,
skipit.sh
的输出必须忽略目录
/home/user/dir1/skip

/home/user> ./skipit.sh  /home/user/dir1/skip dir1 dir2
dir1
dir1/dir    
dir1/dir/skip
dir2
dir2/skip

/home/user> ./skipit.sh  dir1/skip ./dir1 ./dir2
./dir1
./dir1/dir    
./dir1/dir/skip
./dir2
./dir2/skip

/home/user> ./skipit.sh  ../user/dir1/skip ./dir1 ./dir2
./dir1
./dir1/dir    
./dir1/dir/skip
./dir2
./dir2/skip

/home/user> ./skipit.sh  dir1/skip /home/user/dir1 /home/user/dir2
/home/user/dir1
/home/user/dir1/dir    
/home/user/dir1/dir/skip
/home/user/dir2
/home/user/dir2/skip
试试这个:

#!/bin/bash

SKIP="$(sed -r 's|^(\.?\./)*||' <<<$1)"
shift

for arg in "${@:-.}"; do
  root="$(realpath "$arg")"
  find "$root" -regex ".*$SKIP$" -prune -o -print
done
输出:

/tmp/test $ ./test.sh dir/skip dir1/skip/..
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/skip

/tmp/test $ ./test.sh /tmp/test/dir1/skip dir1 dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip

/tmp/test $ ./test.sh dir1/skip dir1 dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip

/tmp/test $ ./test.sh ../test/dir1/skip ./dir1 ./dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip

/tmp/test $ ./test.sh dir1/skip /tmp/test/dir1 /tmp/test/dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip
/tmp/test$。/test.sh dir/skip dir1/skip/。。
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/测试/指令1/跳过
/tmp/test$./test.sh/tmp/test/dir1/skip dir1 dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/测试/目录2/跳过
/tmp/测试$./test.sh目录1/跳过目录1目录2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/测试/目录2/跳过
/tmp/test$./test.sh../test/dir1/skip./dir1./dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/测试/目录2/跳过
/tmp/test$./test.sh dir1/skip/tmp/test/dir1/tmp/test/dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip
这本书非常棒,而且易于阅读/维护;-)

与此同时,我也在研究这个问题,并写了这样的东西:

#!/bin/bash

SKIP="$1"
shift

# if $SKIP does not exist => fast version
if [[ ! -d "$SKIP" ]];  then
  find -H "${@:-.}"
fi

# check what is available to compute real path
shopt -sq expand_aliases
if type realpath &>/dev/null;   then
  alias rp='realpath'
elif type readlink &>/dev/null; then
  alias rp='readlink -fn'
elif type perl &>/dev/null;     then
  alias rp='perl -e '\''use Cwd "abs_path"; print abs_path("$ARGV[1]");'\'
else
  alias rp='echo'
fi

SKIP=$( rp "$SKIP" )

for dir in "${@:-.}"
do
  if [[ -e $dir ]];   then
    dir=$( rp "$dir" )
    find -H "$dir" -path "$SKIP" -prune -o -print
  fi
done

事实上,原始代码更复杂,可以在

中找到,谢谢,但是我不能设置变量DIR和SKIP,它们取决于我的脚本参数。请看我问题的底部。例如,如果存在目录
dir/a/skip
,您的答案将失败。Cheers@olibre不,没有。你只需要正确地整合你的论点。请参阅更新的答案。很抱歉,如果
$1
是绝对路径,则此选项无效。或者如果
$1
是相对路径,如
。/maindir/dir/skip
。我正在寻找一个更通用的解决方案,它适用于所有情况。例如,我还使用了选项
-regex
,看看它是否相关。。。干杯;-)我已经更新了我的问题。希望现在更清楚。我根据
-regex
给出了我的想法。对你来说还可以吗?再见,干杯;-)@是的,我想我现在得到了你想要的。试试我最新的答案。
> ./skipit.sh  dir/skip  ./dir
./dir
./dir/b
./dir/a
> ./skipit.sh  ./dir/skip  dir
dir
dir/b
dir/a
> ./skipit.sh  ./dir/skip  dir/skip/..
dir/skip/..
dir/skip/../skip
dir/skip/../b
dir/skip/../a
> find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Construit avec GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b
Fonctions activées : D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS() CBO(level=0) 
/home/user/dir1
├── skip
└── dir
    └── skip
/home/user/dir2
└── skip
/home/user> ./skipit.sh  /home/user/dir1/skip dir1 dir2
dir1
dir1/dir    
dir1/dir/skip
dir2
dir2/skip

/home/user> ./skipit.sh  dir1/skip ./dir1 ./dir2
./dir1
./dir1/dir    
./dir1/dir/skip
./dir2
./dir2/skip

/home/user> ./skipit.sh  ../user/dir1/skip ./dir1 ./dir2
./dir1
./dir1/dir    
./dir1/dir/skip
./dir2
./dir2/skip

/home/user> ./skipit.sh  dir1/skip /home/user/dir1 /home/user/dir2
/home/user/dir1
/home/user/dir1/dir    
/home/user/dir1/dir/skip
/home/user/dir2
/home/user/dir2/skip
#!/bin/bash

SKIP="$(sed -r 's|^(\.?\./)*||' <<<$1)"
shift

for arg in "${@:-.}"; do
  root="$(realpath "$arg")"
  find "$root" -regex ".*$SKIP$" -prune -o -print
done
/tmp/test
├── dir1
│   ├── dir
│   │   └── skip
│   └── skip
└── dir2
    └── skip
/tmp/test $ ./test.sh dir/skip dir1/skip/..
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/skip

/tmp/test $ ./test.sh /tmp/test/dir1/skip dir1 dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip

/tmp/test $ ./test.sh dir1/skip dir1 dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip

/tmp/test $ ./test.sh ../test/dir1/skip ./dir1 ./dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip

/tmp/test $ ./test.sh dir1/skip /tmp/test/dir1 /tmp/test/dir2
/tmp/test/dir1
/tmp/test/dir1/dir
/tmp/test/dir1/dir/skip
/tmp/test/dir2
/tmp/test/dir2/skip
#!/bin/bash

SKIP="$1"
shift

# if $SKIP does not exist => fast version
if [[ ! -d "$SKIP" ]];  then
  find -H "${@:-.}"
fi

# check what is available to compute real path
shopt -sq expand_aliases
if type realpath &>/dev/null;   then
  alias rp='realpath'
elif type readlink &>/dev/null; then
  alias rp='readlink -fn'
elif type perl &>/dev/null;     then
  alias rp='perl -e '\''use Cwd "abs_path"; print abs_path("$ARGV[1]");'\'
else
  alias rp='echo'
fi

SKIP=$( rp "$SKIP" )

for dir in "${@:-.}"
do
  if [[ -e $dir ]];   then
    dir=$( rp "$dir" )
    find -H "$dir" -path "$SKIP" -prune -o -print
  fi
done