1

我正在尝试将 find 与大括号扩展和 eval 结合使用来查找子文件夹中的许多文件。当我这样做时:

nr1=1001
nr2=1500
eval ls abc*_{$nr1..$nr2}*

它按我的预期工作。但是,当我尝试这样的事情时:

eval find path/to/folder -name "abc*_{$nr1..$nr2}*"

我收到错误消息:

find: paths must precede expression: abc*_{1001..1500}*
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

我尝试了使用和不使用 eval 的不同组合,但似乎没有任何效果。基本上我需要 find 命令来使用大括号扩展,其中使用变量和文件名中的其他元字符。虽然我不一定需要使用 eval ,但我必须承认我并不完全理解它。

4

1 回答 1

3

使用eval容易出错,这包括在处理具有其他人选择的名称的文件时引入安全漏洞。不要这样做。(除了一般的警告——扩展为正在运行的命令的foo{1..3}三个单独的参数foo1foo2, 和参数传递给即使没有)。foo3find-namefind -name eval

eval与您的第一个命令的非基于等效项是:

args=( )
for ((i=nr1; i<=nr2; i++)); do
  args+=( abc*_"$i"* )
done
ls "${args[@]}"

对于第二个命令,您最终会得到更接近于:

find_args=( )
for ((i=nr1; i<=nr2; i++)); do
  find_args+=( -name "abc*_${i}*" -o )
done
find path/to/folder '(' "${find_args[@]}" -false ')' -print

请注意,用于填充存储在数组中的参数流中-false最后一个的右侧。-o-name foo -o name bar -o name bazfind_args


但是,在这两种情况下,您都会冒着在大范围的命令行上耗尽空间的风险(使用原始代码也有风险!)。我建议在运行操作find过滤数字范围:

digits_re='_([[:digit:]]+)([^[:digit:]]|$)'
while IFS= read -r -d '' filename; do
  dirname=${filename%/*}
  basename=${filename##*/}
  if [[ $basename =~ $digits_re ]]; then
    number=${BASH_REMATCH[1]}
    if (( number >= nr1 && number <= nr2 )); then
      printf '%q\n' "$filename"  # for human consumption
      # use '%s\0' instead for a NUL-delimited stream for programmatic use.
    fi
  fi
done < <(find path/to/folder -name 'abc*_[[:digit:]]*' -print0)
于 2017-07-24T16:50:21.177 回答