Bash + 检查文件是否存在于路径 home ~

3
我还没有发现处理这种特定情况的方法。或许有一种简单的方法我忽略了,而不是检查一个字符串以抓住这种情况。当我检查输入文件是否存在时,如果输入是 ~/filecheck ,那么这个方法就行不通了。即使文件在我的主文件夹中,我也会得到负面结果。如果对脚本的任何部分进行改进的建议,我一定会非常感激。我还必须使用输入而不是参数。感谢您的任何帮助。
我的测试脚本
read -p "Enter: " input
echo $input
if [ -f $input ]; then
                read -p "Do you REALLY want to delete this file?:" input2
                if [[ $input2='y' || $input2 = 'Y' ]]
                 then
                        rm -f $input
                elif [[ $input2='n' || $input2='N' ]]
                then
                        exit
                else
                        echo "Invaild Option"
                        exit
                fi

else
 echo Invaild Option!
 exit
fi

它确实有效:input扩展为~/filecheck,因此[ -f $input ]将检查当前目录中的~目录中是否存在名为filecheck的文件。你还期望什么?看起来你并不真正理解~扩展发生的时机。就像$HOME/filecheck会给你相同类型的结果一样。 - gniourf_gniourf
“~”不会被扩展,因为它是一个输入。请尝试一下,这样你就能理解我的问题了。直到anubhava在下面指出这个差异,我实际上并没有注意到。这是有道理的,因为输入不在bash中。 - user3590149
3个回答

2

由于您输入的字符串为~/filecheck,当在[ -f $input ]条件中使用时,shell不会展开波浪号。

您可以这样使用,但不建议使用,因为用户可能会运行任意命令

if [[ -f $(bash -c "echo $input") ]]; then
    echo "file exists"
fi

编辑: 根据下面的评论,为了避免风险,您可以使用以下命令:bash -c

if [[ -f "${input/\~/$HOME}" ]]; then
    echo "file exists"
fi

不建议使用...就像其他答案中的eval一样。在未经过净化的用户输入上调用命令非常危险。 - gniourf_gniourf
1
@user3590149 只是为了好玩,尝试输入“; ls”,你会发现可以执行任意命令——想象一下有人输入“; rm -rf ”并清除大量文件,这就是我说它危险的原因。(即使在父母指导下,也不要在家里尝试)。我没有解决方案可以给你,除了建立一个自己的转换器,将任何潜在的前导“/”替换为“$HOME/”的扩展:即input=${input/#~\/$HOME/} - gniourf_gniourf
@gniourf_gniourf 我能理解这个观点,但我在重现你的建议时遇到了问题。所以我进入程序“sh program”,接下来我有提示符,我在提示符中输入“〜/filename; ls”,我的输出是预期的。“无效选项”。我尝试了其他选项。“; ls”也不起作用。我可以看到可能会发生什么,但我只是想看到它发生。 - user3590149
@user3590149,你没有看到它是因为ls的输出被[[关键字吃掉了。如果你想看到一些稍微邪恶的事情发生,可以尝试输入以下内容:; touch gniourf,然后你应该会在你的目录中看到一个名为gniourf的文件。 - gniourf_gniourf
@gniourf_gniourf 哇,好了。它很邪恶>>>非常邪恶!...哈哈,感谢您的耐心等待。 - user3590149
显示剩余2条评论

2

在程序的这个部分,如果不使用基于eval的东西,就不能进行波浪线扩展——而且你也不想用用户输入来做。因此,你的低配解决方案将是用$HOME/的扩展替换任何可能的前导~/。以下是你脚本的改编,采用了一种更好的风格:

#!/bin/bash

read -e -p "Enter: " input
input=${input/#~\//$HOME/}   # <--- this is the main idea of this answer (and it's rather poor)
echo "$input"
if [[ -f $input ]]; then
    read -e -p "Do you REALLY want to delete this file? " input2
    if [[ ${input2,,} = y ]]; then
        rm -f -- "$input"
    elif [[ ${input2,,} = n ]]; then
        exit
    else
        echo "Invalid Option"
        exit
    fi

else
    echo "Invalid Option!"
fi
exit

现在,出于好奇,你为什么要花时间去包装rm? 你正在为一个已经存在的程序创建一个笨重的界面,而没有添加任何内容,只是使其功能更弱,使用起来更不方便。


阅读一本带有练习的书。可能有些基础,但我会认真对待每一个例子,并尝试找到完整的解决方案。即使这本书不需要那种详细程度。我发现这样学习更多。再次感谢。 - user3590149
@user3590149 出于好奇,是哪本书? - gniourf_gniourf
我说错了,这个问题来自工作表,不知道它的来源。但是我正在使用两本书作为参考:“The Unix Programming Environment”(作者:Brian Kernighan)和“Learning the bash Shell: Unix Shell Programming”。你有什么推荐吗? - user3590149
你的答案消除了相对路径,与正在执行的程序的位置无关。不过这没关系。 - user3590149
@user3590149 我也不知道这两本书。如果你想了解一些现代Bash的见解,可以看看非常有经验的人写的Bash指南。我可以保证他们只展示了良好的实践方法! - gniourf_gniourf
@user3590149 你说的“它会带走相对路径”是什么意思? - gniourf_gniourf

0
如果您只是想在删除之前询问用户,可以使用以下代码:
rm -i

这将在文件不存在的情况下给您适当的错误提示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接