【问题标题】:Creating an array that stores paths and puts them to a variable创建一个存储路径并将它们放入变量的数组
【发布时间】:2019-09-20 05:45:01
【问题描述】:

我正在编写一个脚本,要求用户输入他们想要更改权限的文件名,如果搜索中出现多个文件并且如果用户想要使用多个文件我将如何处理。

我已经设置了 find 命令并将其设置为存储在路径中。

read -r QUESTION
if [ "$QUESTION" = 1 ];
then
    echo "What is the name of the file you want to make read only?"
    read -r FILENAME
    find ~/ -name "$FILENAME"
    PATH=$(find ~/ -name "$FILENAME")
    echo
    pwd
    /bin/chmod -v 400 "$PATH"
    fi
fi

echo

预期的输出将是用户将能够输入多个文件,他们将能够一次更改所有这些文件的权限。如果他们只想更改 1 个文件并且在 find 中显示多个文件,他们可以选择他们的 1 个文件。

【问题讨论】:

  • BashFAQ #20 涵盖了直接对 find 匹配的文件进行操作或将它们放入数组(不是普通变量!)以便您可以单独对它们进行操作的方法。您也可以直接遍历名称,如this answer
  • 对不起,我还有一些问题,当它的PATH=$() 时会叫什么?第二件事是来自数组让我们说我使用 chmod,我可以在 chmod 末尾调用数组来一次更改所有文件?

标签: arrays bash unix


【解决方案1】:

除非您知道自己在做什么,否则不要覆盖 $PATH。该变量用于查找可执行文件。

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

就像戈登说的;您必须将 find 的输出放入数组而不是变量中。注意引号,否则带空格的文件会出错。

ARRAY=("$(find . -name "my file.txt")")
for file in "${ARRAY[@]}"; do echo $file; done

我冒昧地以我认为您可以根据需要更改它的方式编写脚本。该脚本可以自行解释,但请随时提出问题。你应该自己做一些错误检查;-)

#! /bin/bash

IFS=$'\n'

FOUND=()
echo "Enter a blank filename to stop input"
while read -p "Enter a file name: " file; do
        [ ! -z "${file}" ] || break
        file_found=$(find ${HOME} -name ${file})
        if [ -z "${file_found}" ]; then
            echo "File '$file' not found"
            continue
        fi
        FOUND+=(${file_found})
done

if [ ${#FOUND[@]} -gt 1 ]; then

        echo "Multiple files found, make a choice."
        for ((index=0; index<${#FOUND[@]};index++)); do
                echo "  -> $index = ${FOUND[$index]}"
        done
        echo "  -> 0 1 .. n = Item 0, 1, .., n"
        echo "  -> * = Everything"
        echo "  -> Leave empty to abort"

        read -p "Choice(s): " CHOICE

        if [ -z "${CHOICE}" ]; then
                echo "Nothing chosen, aborting"
        elif [ "${CHOICE}" = "*" ]; then
                chmod -v 400 ${FOUND[@]}
        else
                FILES=()
                IFS=' '
                for choice in ${CHOICE}; do
                        FILES+=("${FOUND[$choice]}")
                done
                chmod -v 400 "${FILES[@]}"
        fi
elif [ ${#FOUND[@]} -eq 1 ]; then
        chmod -v 400 $FOUND
else
        echo "Not found"
        exit 1
fi

exit 0

注意:我之前没有想到这一点,但可以提供一个 here-document 而不是交互式地使用脚本:

$ ./test.sh << EOF
file1.txt
file 2.txt

*
EOF

【讨论】:

  • 如果我们希望用户选择他们想要搜索的目录,或者甚至我们只是默认它从~/开始搜索,那么我们不会使用mydir?您是否只需将输入设置在与​​ mydir 相同的位置?
  • 我不推荐使用ARRAY=($(find ... )),因为它会被带有空格和/或通配符的文件名混淆。 (我主要生活在 macOS 上,其中文件名中的空格很常见。)我会改用 BashFAQ #20 中的一种技术。此外,在引用周围使用双引号,例如 chmod -v 400 "${FILES[@]}"
  • 如果我不想让用户选择他们可以搜索的目录,我会完全删除 MYDIR 变量并在 find 命令中使用 $HOME。 @GordonDavisson 有一个很好的观点。我个人从不使用带有空格的文件,因此当您尝试查找此类文件时,此脚本会中断。你必须使用IFS variable。我会更新我的答案。
  • 感谢您的回复,然后是关于使用数组的第二个问题,如果用户想要调用他们选择的多个文件并位于不同的目录中,然后将所有这些文件放入一个命令中,例如: chmod * * file1 file2 你会怎么做呢?这就是我最初的问题的根源。
  • 我将创建一个循环,其中数组不断填充从用户输入中找到的文件。我会更新脚本。
猜你喜欢
  • 1970-01-01
  • 2022-12-01
  • 2021-05-01
  • 2022-01-26
  • 2012-10-23
  • 2015-10-22
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多