【问题标题】:How to use content of variable in bash to pass to find in script?如何使用 bash 中的变量内容传递给脚本中的查找?
【发布时间】:2016-12-21 10:36:24
【问题描述】:

在 bash 脚本中,我尝试使用变量的内容作为 find 命令的选项:

#!/bin/bash
FILE_EXTENSIONS=( txt png jpg )

FIRST=1
for FILE_EXTENSION in ${FILE_EXTENSIONS[@]} 
do
#   echo "$FILE_EXTENSION"
    if [[ $FIRST == 1 ]]
    then
        FIND_FILTER="-iname '*.$FILE_EXTENSION'"
        FIRST=0
    else
        FIND_FILTER="${FIND_FILTER} -o -iname '*.$FILE_EXTENSION'"
    fi
done
# Read and write only for user and group, ignore case '-iname'
#find . -type f "$FIND_FILTER" -exec chmod 660 {} \;
echo Find filter: $FIND_FILTER
# This might work with some already provided suggestions:
find . -type f $FIND_FILTER
# But this fails so far
find . -type f $FIND_FILTER -exec chmod 660 {} \;        
#EOF

目的是设置适当的访问权限,因为某些文件(例如图片或办公文档)被标记为可执行文件。

所以实际上上面的脚本有几个文件扩展名连接的数组,但脚本显示了问题。

第一种方法是遍历最终数组并每次调用 find。但是从运行时的角度来看,一次又一次地搜索是愚蠢的。

我也可以简单地在 python 中执行此操作,但有一次我想我想在 bash 中使用 linux 基本方法来解决它。

看起来 FIND_FILTER 变量的内容是正确的(至少是使用 echo 打印的内容),但是......它不起作用。

有什么建议吗?

【问题讨论】:

    标签: linux string bash find quotes


    【解决方案1】:

    您开始(几乎)正确地使用了数组,但随后放弃了它们以使用空格分隔的字符串。继续使用数组。

    1. 总是引用@-indexed 数组的扩展;否则,没有理由使用@ 而不是*
    2. 作为一般规则,避免使用全大写的变量名称;它们(大部分)保留给 shell 使用。
    3. 将由-o 连接的过滤器括在转义括号中,以便find 将它们视为除-type 主要条件之外的单个条件。
    4. 使用-exec ... +,这样chmod 可以在每次调用时对多个文件进行操作,而不是为每个文件单独调用一次。

    #!/bin/bash
    file_extensions=( txt png jpg )
    
    first=1
    for ext in "${file_extensions[@]}"
    do
    #   echo "$ext"
        if [[ $first == 1 ]]
        then
            find_filter=(-iname "*.$ext")
            first=0
        else
            find_filter+=( -o -iname "*.$ext")
        fi
    done
    
    
    # Read and write only for user and group, ignore case '-iname'
    find . -type f \( "${find_filter[@]}" \) -exec chmod 660 +
    

    【讨论】:

    • @Benoit 感谢您整理我仓促写下的答案。
    • 谢谢@chepner - 这拯救了我的一天。我现在更了解如何使用数组以及最重要的 ( ) 查找语法以及引用它们的需要!
    【解决方案2】:

    好的,我找到了它不起作用的原因

    $ find . $FIND_ARGS &       # Does not work
    [1] 6312    
    $ cat /proc/6312/cmdline
    find . -iname '*.png'
    
    $ find . -iname '*.png' &   # Works
    [1] 8901
    $ cat /proc/8901/cmdline
    find . -iname *.png
    

    因此,直接调用命令时的引号仅用于 bash 不扩展参数。当您间接启动命令时,您必须删除这些引号。

    【讨论】:

    • 感谢 Benoit,我确认这适用于简单的情况(即使我不明白为什么)。但是一旦我尝试将结果用作'-exec chmod 660 {} \;'的参数它失败了: Find filter: -iname filter.txt -o -iname z.png -o -iname *.jpg find: unknown predicate `-iname *.txt -o -iname *.png -o -iname *.jpg '
    猜你喜欢
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多