如何检查Shell脚本中是否存在文件


175

我想编写一个Shell脚本来检查某个文件archived_sensor_data.json是否存在,如果存在,则将其删除。在http://www.cyberciti.biz/tips/find-out-if-file-exists-with-conditional-expressions.html之后,我尝试了以下操作:

[-e archived_sensor_data.json] && rm archived_sensor_data.json

但是,这会引发错误

[-e: command not found

当我尝试test_controller使用./test_controller命令运行生成的脚本时。代码有什么问题?



2
您必须在方括号“ [”和选项“ -e”之间设置一个或多个空格,与文件名和方括号“]”之间的空格相同
Konstantin Yaniv

Answers:


350

您在括号和之间缺少必需的空格-e

#!/bin/bash
if [ -e x.txt ]
then
    echo "ok"
else
    echo "nok"
fi

12
最后,我添加了两个空格,一个在左方括号后,另一个在右后方空格:[ -e archived_sensor_data.json ] && rm archived_sensor_data.json。该脚本现在似乎可以工作了。
库尔特·皮克

3
这也可以使用if [ -e "$1" ](文件名输入参数)。
爱德华

2
这里的主要区别在于您使用的是“ bash”脚本而不是“ shell”脚本。请注意,您添加的第一行是#!/ bin / bash,因此您要告诉机器使用“ bash”而不是sh。由于SH不承认这样的说法“-e”
尼克·奎瓦斯

29

这是使用的另一种方法ls

(ls x.txt && echo yes) || echo no

如果你想要隐藏的任何输出ls,所以你只能看到是或否,重定向stdoutstderr/dev/null

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no

1
此代码的意思是:“如果ls成功,则存在该文件,否则,则不存在”。如果ls失败,并不表示该文件丢失。可能是其他错误。例如,在root拥有的目录中创建文件,然后尝试ls在普通用户下执行此操作。它将失败Permission denied,并且不等于该文件不存在。
提格伦

9

我的解决方案建议的背景是一个朋友的故事,他在第一份工作的第二周就抹去了一半的构建服务器清理工作。因此,基本任务是确定文件是否存在,如果存在,让我们将其删除。但是这条河上有一些险恶的急流:

  • 一切都是文件。

  • 脚本只有在解决一般任务时才具有真正的力量

  • 一般而言,我们使用变量

  • 我们经常在脚本中使用-f force以避免手动干预

  • 而且也喜欢-r递归以确保我们及时创建,复制和销毁。

请考虑以下情形:

我们有要删除的文件:filesexists.json

该文件名存储在变量中

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

我们也有一个路径变量来使事情变得真正灵活

<host>:~/Documents/thisfolderexists pathtofile=".."

<host>:~/Documents/thisfolderexists ls $pathtofile

filesexists.json  history20170728  SE-Data-API.pem  thisfolderexists

因此,让我们看看-e它是否应该执行该操作。文件是否存在?

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

是的 魔法。

但是,如果意外将文件变量赋值为nuffin,会发生什么情况?

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

什么?它应该返回一个错误...这是故事的开始,整个文件夹是被意外删除的

另一种选择是专门测试我们理解为“文件”的东西

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

0

所以该文件存在...

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

1

所以这不是文件,也许我们不想删除整个目录

man test 有以下说法:

-b FILE

       FILE exists and is block special

-c FILE

       FILE exists and is character special

-d FILE

       FILE exists and is a directory

-e FILE

       FILE exists

-f FILE

       FILE exists and is a regular file

...

-h FILE

       FILE exists and is a symbolic link (same as -L)

4

在内部,无论如何,rm命令必须测试文件是否存在,
那么为什么还要添加另一个测试?刚发行

rm filename

无论那里是否存在,它都会消失。
如果您不需要有关不存在文件的任何消息,请使用rm -f。

如果文件不存在,如果您需要采取一些措施,那么您必须自己进行测试。根据您的示例代码,在这种情况下不是这种情况。


1
对于rm命令,这实际上是一个很有效的答案。对于其他命令,我建议使用-e进行测试。
warhansen

除了不是问题要问的。
蜡笔小新

1
如果您阅读了整个问题,包括“ ...和(如果是)...将其删除”部分),那么问题的实质就是问题。
TG

1

如果您使用的是NFS,则“测试”是一个更好的解决方案,因为您可以在NFS发生故障的情况下向其中添加超时:

time timeout 3 test -f 
/nfs/my_nfs_is_currently_down
real    0m3.004s <<== timeout is taken into account
user    0m0.001s
sys     0m0.004s
echo $?
124   <= 124 means the timeout has been reached

“ [-e my_file]”构造将冻结,直到NFS再次起作用:

if [ -e /nfs/my_nfs_is_currently_down ]; then echo "ok" else echo "ko" ; fi

<no answer from the system, my session is "frozen">

test并且[是同义词。您也可以使用timeoutwith [test如果NFS挂起,它也将冻结。
另一个人
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.