为什么第二个命令有效,为什么不是第一个?有什么不同?
Why the second command works and why not first? what is the difference?
我在 shell 脚本中遇到以下奇怪问题。
当我像下面这样执行时它不起作用:
excom='/Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\*'
findcom=$(find /Development/temp_try ! \( -path $excom \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
如果我像下面那样执行,它工作正常:
findcom=$(find /Development/temp_try ! \( -path /Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\* \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
第一个输出是:
/Development/temp_try/f1
/Development/temp_try/f2
/Development/temp_try/f3
/Development/temp_try/f4
/Development/temp_try/f5
/Development/temp_try/f6
/Development/temp_try/f7
/Development/temp_try/f8
/Development/temp_try/try10
/Development/temp_try/log_test
/Development/temp_try/try10v
/Development/temp_try/try10v1
/Development/temp_try/try10j
/Development/temp_try/try10j1
/Development/temp_try/testing1/f1
/Development/temp_try/testing1/f2
/Development/temp_try/testing1/f3
/Development/temp_try/testing/test1/f1
/Development/temp_try/testing/test1/f2
/Development/temp_try/testing/test1/f3
/Development/temp_try/testing/test1/f4
/Development/temp_try/testing/test1/f5
/Development/temp_try/testing/test1/f6
/Development/temp_try/testing/test1/f7
/Development/temp_try/testing/test1/f8
/Development/temp_try/testing/f1
/Development/temp_try/testing/f2
/Development/temp_try/testing/f3
/Development/temp_try/testing/f4
/Development/temp_try/testing/f5
/Development/temp_try/testing/f6
/Development/temp_try/testing/f7
/Development/temp_try/testing/f8
/Development/temp_try/try10j1_working
/Development/temp_try/try11
/Development/temp_try/try11_original
/Development/temp_try/try8
第二个输出是:
/Development/temp_try/f1
/Development/temp_try/f2
/Development/temp_try/f3
/Development/temp_try/f4
/Development/temp_try/f5
/Development/temp_try/f6
/Development/temp_try/f7
/Development/temp_try/f8
/Development/temp_try/try10
/Development/temp_try/log_test
/Development/temp_try/try10v
/Development/temp_try/try10v1
/Development/temp_try/try10j
/Development/temp_try/try10j1
/Development/temp_try/try10j1_working
/Development/temp_try/try11
/Development/temp_try/try11_original
/Development/temp_try/try8
第二个完美排除了第一个没有的目录。我不知道它们有何不同....
感谢您的回答和评论,现在我明白了问题,可以解决问题。
#!/usr/bin/ksh
filepath="/Development/temp_try"
searchstring="corp.abc.com"
while read exfile
do
lasc=${exfile##${exfile%%?}}
if [ "$lasc" = "/" ]; then
exfile="$exfile*"
fi
if [ "$excom" = "" ]; then
excom="$exfile"
else
#excom="$excom -o -path '$exfile'"
set -A excom "$excom" '-o' '-path' "$exfile"
fi
done <input4
echo "The exclude command is ${excom[@]}"
findcom=$(find $filepath ! \( -path "${excom[@]}" \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF $searchstring {} \;)
for filename in $findcom
do
echo $filename
done
我的 input4 文件包含以下行:
/Development/temp_try/testing/
/Development/temp_try/testing1/
不要将命令行(全部或部分)存储在简单变量中,因为它会在 shell 中的变量扩展时产生许多问题。
最好像这样存储在 shell 数组中
excom=('/Development/temp_try/testing/*' -o -path '/Development/temp_try/testing1/*')
findcom=$(find /Development/temp_try ! \( -path "${excom[@]}" \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
在单引号字符串中,\
没有特殊意义。所以
的结果
excom='/Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\*'
是excom
的值会包含两个反斜杠字符。
反斜杠字符在文件名扩展中并不特殊,所以当$excom
的值被文件名扩展和分词时(因为它的扩展没有被引用),反斜杠字符仍然是普通字符。所以展开
find /Development/temp_try ! \( -path $excom \) ...
有字面意思:
find
/Development/temp_try
!
(
-path
/Development/temp_try/testing/\*
-o
-path
/Development/temp_try/testing1/\*
没有任何内容与模式 /Development/temp_try/testing/\*
匹配,因为您的文件名不包含反斜杠。
你在定义 excom 时是否遗漏了反斜杠:
excom='/Development/temp_try/testing/* -o -path /Development/temp_try/testing1/*'
那么文件名模式将在调用 find 时展开。在这种情况下,find /Development/temp_try ! \( -path $excom \) ...
将扩展为:
find
/Development/temp_try
!
(
-path
/Development/temp_try/testing/f1
/Development/temp_try/testing/f2
/Development/temp_try/testing/f3
...
这也不是您想要的,因为 -path
谓词后面需要正好跟一个模式,而不是文件名列表。
因此,您需要将 excom
的值作为引用词的列表传递。在 bash 中唯一简单的方法是使用数组,因为您可以将数组扩展为引用数组值的列表:
excom=("/Development/temp_try/testing/*"
-o -path "/Development/temp_try/testing1/*")
findcom=$(find /Development/temp_try ! \( -path "${excom[@]}" \) \
-type f \( ! -name "*.HPSEPFQDN.*" ! -name "*.HPSEPIPCHG."* \) \
-exec grep -lF "corp.abc.com" {} \;)
(未引用的 findcom
的定义假定 -exec grep
命令生成的文件名的名称中不会包含空格或模式元字符。一般来说,这不是安全假设。)
我在 shell 脚本中遇到以下奇怪问题。
当我像下面这样执行时它不起作用:
excom='/Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\*'
findcom=$(find /Development/temp_try ! \( -path $excom \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
如果我像下面那样执行,它工作正常:
findcom=$(find /Development/temp_try ! \( -path /Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\* \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
第一个输出是:
/Development/temp_try/f1
/Development/temp_try/f2
/Development/temp_try/f3
/Development/temp_try/f4
/Development/temp_try/f5
/Development/temp_try/f6
/Development/temp_try/f7
/Development/temp_try/f8
/Development/temp_try/try10
/Development/temp_try/log_test
/Development/temp_try/try10v
/Development/temp_try/try10v1
/Development/temp_try/try10j
/Development/temp_try/try10j1
/Development/temp_try/testing1/f1
/Development/temp_try/testing1/f2
/Development/temp_try/testing1/f3
/Development/temp_try/testing/test1/f1
/Development/temp_try/testing/test1/f2
/Development/temp_try/testing/test1/f3
/Development/temp_try/testing/test1/f4
/Development/temp_try/testing/test1/f5
/Development/temp_try/testing/test1/f6
/Development/temp_try/testing/test1/f7
/Development/temp_try/testing/test1/f8
/Development/temp_try/testing/f1
/Development/temp_try/testing/f2
/Development/temp_try/testing/f3
/Development/temp_try/testing/f4
/Development/temp_try/testing/f5
/Development/temp_try/testing/f6
/Development/temp_try/testing/f7
/Development/temp_try/testing/f8
/Development/temp_try/try10j1_working
/Development/temp_try/try11
/Development/temp_try/try11_original
/Development/temp_try/try8
第二个输出是:
/Development/temp_try/f1
/Development/temp_try/f2
/Development/temp_try/f3
/Development/temp_try/f4
/Development/temp_try/f5
/Development/temp_try/f6
/Development/temp_try/f7
/Development/temp_try/f8
/Development/temp_try/try10
/Development/temp_try/log_test
/Development/temp_try/try10v
/Development/temp_try/try10v1
/Development/temp_try/try10j
/Development/temp_try/try10j1
/Development/temp_try/try10j1_working
/Development/temp_try/try11
/Development/temp_try/try11_original
/Development/temp_try/try8
第二个完美排除了第一个没有的目录。我不知道它们有何不同....
感谢您的回答和评论,现在我明白了问题,可以解决问题。
#!/usr/bin/ksh
filepath="/Development/temp_try"
searchstring="corp.abc.com"
while read exfile
do
lasc=${exfile##${exfile%%?}}
if [ "$lasc" = "/" ]; then
exfile="$exfile*"
fi
if [ "$excom" = "" ]; then
excom="$exfile"
else
#excom="$excom -o -path '$exfile'"
set -A excom "$excom" '-o' '-path' "$exfile"
fi
done <input4
echo "The exclude command is ${excom[@]}"
findcom=$(find $filepath ! \( -path "${excom[@]}" \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF $searchstring {} \;)
for filename in $findcom
do
echo $filename
done
我的 input4 文件包含以下行:
/Development/temp_try/testing/
/Development/temp_try/testing1/
不要将命令行(全部或部分)存储在简单变量中,因为它会在 shell 中的变量扩展时产生许多问题。
最好像这样存储在 shell 数组中
excom=('/Development/temp_try/testing/*' -o -path '/Development/temp_try/testing1/*')
findcom=$(find /Development/temp_try ! \( -path "${excom[@]}" \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
在单引号字符串中,\
没有特殊意义。所以
excom='/Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\*'
是excom
的值会包含两个反斜杠字符。
反斜杠字符在文件名扩展中并不特殊,所以当$excom
的值被文件名扩展和分词时(因为它的扩展没有被引用),反斜杠字符仍然是普通字符。所以展开
find /Development/temp_try ! \( -path $excom \) ...
有字面意思:
find
/Development/temp_try
!
(
-path
/Development/temp_try/testing/\*
-o
-path
/Development/temp_try/testing1/\*
没有任何内容与模式 /Development/temp_try/testing/\*
匹配,因为您的文件名不包含反斜杠。
你在定义 excom 时是否遗漏了反斜杠:
excom='/Development/temp_try/testing/* -o -path /Development/temp_try/testing1/*'
那么文件名模式将在调用 find 时展开。在这种情况下,find /Development/temp_try ! \( -path $excom \) ...
将扩展为:
find
/Development/temp_try
!
(
-path
/Development/temp_try/testing/f1
/Development/temp_try/testing/f2
/Development/temp_try/testing/f3
...
这也不是您想要的,因为 -path
谓词后面需要正好跟一个模式,而不是文件名列表。
因此,您需要将 excom
的值作为引用词的列表传递。在 bash 中唯一简单的方法是使用数组,因为您可以将数组扩展为引用数组值的列表:
excom=("/Development/temp_try/testing/*"
-o -path "/Development/temp_try/testing1/*")
findcom=$(find /Development/temp_try ! \( -path "${excom[@]}" \) \
-type f \( ! -name "*.HPSEPFQDN.*" ! -name "*.HPSEPIPCHG."* \) \
-exec grep -lF "corp.abc.com" {} \;)
(未引用的 findcom
的定义假定 -exec grep
命令生成的文件名的名称中不会包含空格或模式元字符。一般来说,这不是安全假设。)