bash - 如何使用 exec 执行任意查找命令
问题描述
在 bash 脚本中,我想根据我传递给脚本的参数定义一个commandstring
指定选项和初选的 。find
然后我想用这些选项和初选exec
来调用。find
一般来说,我希望能够定义我可以在命令行上运行的任何调用,并且它在一个子shell中。特别是,我希望能够排除包含 linefeed=LF=newline= 的文件名。find
exec
$'\n'
当我使用参数调用下面的示例脚本时easy
,它会打印所有包含空格的文件名,并按exec
预期工作。但是,如果我使用参数调用它hard
,则exec
无法按预期工作。
正如您在下面看到的,如果我对 command 进行硬编码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 '%s\n' "first argument=${1} but must be either easy or hard."
exit 1
fi
declare -p commandstring; printf '%s\n' "commandstring=${commandstring}";
printf -- '-------------------------------\n%s\n' "hard-coded hard commandstring inside this script:"
find . -name *$'\n'*
printf -- '-------------------------------\n%s\n' "hard-coded easy commandstring inside this script:"
find . -name *[[:space:]]*
printf -- '-------------------------------\n%s\n' 'Now test exec with the commandstring, inside $( subshell )'
junk=$(
{
set -f
printf '%s\n' "Now inside subshell, will exec"
declare -p commandstring; printf '%s\n' "commandstring=${commandstring}";
exec $commandstring
} > /dev/stderr ;
)
printf '%s\n' 'got past $( subshell ); now try to exec it inside the script'
exec $commandstring
printf '%s\n' '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
推荐阅读
- javascript - 创建动态组件 VUE
- swift - Travis CI - Swift 包管理 - 结帐已经存在?
- ms-office - 在后端使用 Microsoft Office Word
- java - Eclipse调试到java源,不列出源类的成员变量
- objective-c - glClearStencil(AStencil)的金属当量是多少
- python - 打开一个文本文件以在 spyder 中使用
- scala - “错误:前向引用扩展了变量计数器的定义”
- python - 如何从经纬度过滤国家?
- c - C项目结构、代码共享和编译代码的依赖
- php - 在 Codeigniter 中使用哈希值比较密码无效