【问题标题】:how to use exec to execute an arbitrary find command如何使用 exec 执行任意查找命令
【发布时间】:2019-10-21 17:37:52
【问题描述】:

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

一般来说,我希望能够定义 any 调用 find 可以在命令行上运行,并在子 shell 中定义 exec。特别是,我希望能够排除包含 linefeed=LF=newline=$'\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 '%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
> 

【问题讨论】:

标签: bash find exec linefeed


【解决方案1】:

感谢答案:以下脚本的行为符合预期。

#!/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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 2017-06-19
    相关资源
    最近更新 更多