我想使用$SKIP
跳过子目录find
。
遗憾的是这个基本命令在所有情况下都不起作用:
find $DIR -path $SKIP -prune -o print
请帮我改进脚本skipit.sh
:
#!/bin/bash
SKIP=$1
shift
find "${@:-.}" -path "$SKIP" -prune -o -print
该示例基于以下目录树:
dir
├── skip
├── a
└── b
行:
> ./skipit.sh dir/skip dir
dir
dir/a
dir/b
失败:
> ./skipit.sh dir/skip ./dir
./dir
./dir/skip
./dir/b
./dir/a
失败:
> ./skipit.sh ./dir/skip dir
dir
dir/skip
dir/b
dir/a
-regex
> cat skipit.sh
#!/bin/bash
SKIP=${1#./} #remove leading './'
shift
find "${@:-.}" -regex "[.]?/?$SKIP" -prune -o -print
行:
> ./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
版本> 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)
我可以使用realpath
但由于默认情况下未安装此命令,因此我不想强迫其他用户安装它。我也可以使用readlink
,但我更喜欢基于find
功能的解决方案;)
/home/user/dir1
├── skip
└── dir
└── skip
/home/user/dir2
└── skip
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
答案 0 :(得分:2)
试试这个:
#!/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
答案 1 :(得分:0)
Ansgar Wiechers's answer非常棒且易于阅读/维护; - )
与此同时,我也在研究这个问题并写了类似的东西:
#!/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
事实上,原始代码更复杂,可以在https://github.com/olibre/ShellScripts/blob/master/rmdups.sh
找到