2

我正在以编程方式构建一个查找命令:

find  "${SRC_DIR}" "${FILE_NAMES}" -type f -mtime +14 -level 0

其中 FILE_NAMES 是我需要匹配的文件模式,它是一个简单的以空格分隔的模式列表(*.txt、*.html 等)。

要为 find 命令正确格式化此列表,它不能只是一个列表,它必须看起来像:

-name *.txt -o -name *.html

我的解决方案是使用:

FILE_NAMES=$(echo ${FILES} | sed -e 's/\s+/-o -name /g')

但它不起作用,特别是它似乎不明白我想替换空格。有没有人有更好的方法来做到这一点?

4

3 回答 3

1

并非所有 seds 都支持类似 perl 的空格、数字等占位符。我没有办法测试您的确切情况,但以下应该是一个很好的指南。

另外,请注意find -predicate -predicate ....默认情况下是 ANDed。要完成这项-o工作,您必须将整个事情包裹在( (parens) )AND 中,这样外壳就不会将括号视为启动子外壳的请求,您必须转义括号,即\( .... -o .... \). 所以这导致我们

 set -vx; SRC_DIR="." ; FILE_NAMES="a b c"
 find  "${SRC_DIR}" \( $(echo "$FILE_NAMES"| sed 's/ / -o -name /g;s/^/-name /') \) -type f -mtime +14 -level 0

输出

+ echo 'a b c'
+ sed 's/ / -o -name /g;s/^/-name /'
+ find . '\( -name a -o -name b  -o -name c \)' -type f -mtime +14 -level 0
find: invalid predicate `-level'

这只是表明我的 find 也不支持 -level 。

编辑删除"\(....\).

如果您使用的是 ksh93,则可以使用变量修饰符,例如

${FILE_NAME// / -o -name}

但是您需要仅连接开头-name或对 FILE_NAME 的保存值进行第二次替换。

您可以通过发出以下 cmd 来查看您是否有 ksh93

echo ${.sh.version}

如果你得到一个值,那么你有 ksh93。

IHTH

于 2012-08-30T21:52:22.153 回答
1

克什:

FILES='*.txt *.html'
FILE_NAMES=$(
  # $() runs this script in a subshell
  conjunction=""
  set -f   # turn off file pattern expansion
  for patt in $FILES; do
    printf "%s -name '%s' " "$conjunction" "$patt"
    conjunction="-o"
  done
)
find  "${SRC_DIR}" ${FILE_NAMES} -type f -mtime +14 -level 0

请注意,$FILE_NAMES没有引用- 您希望 shell 将变量拆分为单独的单词。

于 2012-08-30T23:17:07.177 回答
0

采取不同的方法可能更容易:

find ${SRC_DIR} -type f -mtime +14 | egrep '\.(txt|html)$'

我忽略了这-level 0一点,因为我不知道它的用途 - 它在我手头的版本中不存在。你总是可以把它放回去...

于 2012-08-30T21:35:04.653 回答