如何使用 exec 执行任意查找命令



在 bash 脚本中,我想定义一个commandstring,它根据我传递给脚本的参数指定find的选项和主选项。然后,我想使用exec来调用具有这些选项和主选项的find

通常,我希望能够定义可以在命令行上运行的任何find调用,并将其exec在子shell中。特别是,我希望能够排除包含换行符=LF=换行符=$'n'的文件名。

当我使用参数easy调用下面的示例脚本时,它会打印所有包含空格的文件名,并且exec按预期工作。但是如果我用参数hard调用它,那么exec就不能按预期工作。

如下所示,如果我对命令进行硬编码find . -name *$'n'*,它会按预期工作。 但如果我把它放进commandstring,它就没有。有没有办法解决这个问题?

我没有更高版本的 bash,在我的 macOS 上坚持使用 3 版。

该脚本称为junk

#!/bin/bash  
set -f
bash --version
if [[ ${1} = easy ]]
then
printf '***%s***n' "${1}"
commandstring="find .  -name *[[:space:]]* "
elif [[ ${1} = hard ]]
then
printf '***%s***n' "${1}"
commandstring="find . -name *$'n'* "
else
printf '%sn' "first argument=${1} but must be either easy or hard."
exit 1
fi
declare -p commandstring; printf '%sn' "commandstring=${commandstring}";
printf -- '-------------------------------n%sn' "hard-coded hard commandstring inside this script:"
find . -name *$'n'* 
printf -- '-------------------------------n%sn' "hard-coded easy commandstring inside this script:"
find .  -name *[[:space:]]* 
printf -- '-------------------------------n%sn' 'Now test exec with the commandstring, inside $( subshell )'
junk=$( 
{
set -f
printf '%sn' "Now inside subshell, will exec"
declare -p commandstring; printf '%sn' "commandstring=${commandstring}";
exec $commandstring  
} > /dev/stderr ; 
)
printf '%sn' 'got past $( subshell ); now try to exec it inside the script'
exec $commandstring  
printf '%sn' 'should never get here, because it comes after exec'

它的行为方式:

> find . -type f
./easy
./newlineBEF
newlineAFT
./tabBEF    tabAFT
./okay
./spaceBEF  AFTspace
./zzz
> ls -lT ./*
-rw-r--r--  1 BNW  staff  10 Oct 19 20:15:36 2019 ./easy
-rw-r--r--  1 BNW  staff  11 Oct 20 12:08:24 2019 ./newlineBEF?newlineAFT
-rw-r--r--  1 BNW  staff  13 Oct 19 20:15:43 2019 ./okay
-rw-r--r--  1 BNW  staff  14 Oct 20 12:37:19 2019 ./spaceBEF  AFTspace
-rw-r--r--  1 BNW  staff  10 Oct 19 20:14:01 2019 ./tabBEF?tabAFT
-rw-r--r--  1 BNW  staff   0 Feb 26 11:30:54 2019 ./zzz
> junk easy
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
***easy***
declare -- commandstring="find .  -name *[[:space:]]* "
commandstring=find .  -name *[[:space:]]* 
-------------------------------
hard-coded hard commandstring inside this script:
./newlineBEF
newlineAFT
-------------------------------
hard-coded easy commandstring inside this script:
./newlineBEF
newlineAFT
./tabBEF    tabAFT
./spaceBEF  AFTspace
-------------------------------
Now test exec with the commandstring, inside $( subshell )
Now inside subshell, will exec
declare -- commandstring="find .  -name *[[:space:]]* "
commandstring=find .  -name *[[:space:]]* 
./newlineBEF
newlineAFT
./tabBEF    tabAFT
./spaceBEF  AFTspace
got past $( subshell ); now try to exec it inside the script
./newlineBEF
newlineAFT
./tabBEF    tabAFT
./spaceBEF  AFTspace
> junk hard
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
***hard***
declare -- commandstring="find . -name *$'\n'* "
commandstring=find . -name *$'n'* 
-------------------------------
hard-coded hard commandstring inside this script:
./newlineBEF
newlineAFT
-------------------------------
hard-coded easy commandstring inside this script:
./newlineBEF
newlineAFT
./tabBEF    tabAFT
./spaceBEF  AFTspace
-------------------------------
Now test exec with the commandstring, inside $( subshell )
Now inside subshell, will exec
declare -- commandstring="find . -name *$'\n'* "
commandstring=find . -name *$'n'* 
got past $( subshell ); now try to exec it inside the script
> 

感谢答案:以下脚本按预期运行。

#!/bin/bash  
set -f
bash --version
argARRAY=( "$@" )
declare -p argARRAY
find "${argARRAY[@]}"

两个调用:

> junk .
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
declare -a argARRAY='([0]=".")'
.
./easy
./newlineBEF
newlineAFT
./tabBEF    tabAFT
./okay
./spaceBEF  AFTspace
./zzz
> junk  . -name *$'n'*
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
declare -a argARRAY='([0]="." [1]="-name" [2]="*
*")'
./newlineBEF
newlineAFT

最新更新