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

Kur*_*eek 151 shell

我想编写一个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
Run Code Online (Sandbox Code Playgroud)

但是,这会引发错误

[-e: command not found
Run Code Online (Sandbox Code Playgroud)

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

chr*_*s01 312

您在支架和-e:之间缺少必需的空格:

#!/bin/bash
if [ -e x.txt ]
then
    echo "ok"
else
    echo "nok"
fi
Run Code Online (Sandbox Code Playgroud)

  • 我最后添加了两个空格,一个在开放方括号之后,一个在结束之前:`[ - e archived_sensor_data.json] && rm archived_sensor_data.json`.该脚本现在似乎有效. (11认同)
  • 这里的主要区别在于您使用的是“bash”脚本而不是“shell”脚本。请注意,您添加的第一行是 #!/bin/bash,因此您告诉机器使用“bash”而不是 sh。因为 sh 无法识别该参数 "-e" (5认同)
  • 这也可以使用`if [-e“ $ 1”]`(文件名输入参数)。 (3认同)
  • 我相信这也适用于Bourne Shell`sh` (2认同)
  • `-e` POSIX shell 兼容吗? (2认同)

Phi*_*ide 22

这是一种替代方法,使用ls:

(ls x.txt && echo yes) || echo no
Run Code Online (Sandbox Code Playgroud)

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

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no
Run Code Online (Sandbox Code Playgroud)

  • 这段代码的意思是:“如果`ls`成功,则有这样的文件,否则,没有”。如果 `ls` 失败,并不意味着文件丢失。这可能是其他一些错误。例如,在root拥有的目录中创建文件,并尝试在普通用户下执行`ls`。它将因“权限被拒绝”而失败,这并不等同于文件不存在。 (8认同)
  • @Tigran 这是一个很好的区别,就我而言并不重要,但感谢您的指出。 (2认同)

T G*_*T G 7

在内部,rm命令必须测试文件是否存在,
那么为什么要添加另一个测试呢?只是问题

rm filename
Run Code Online (Sandbox Code Playgroud)

它会在那之后消失,无论它是否存在.
使用rm -f是您不希望有关于不存在的文件的任何消息.

如果您不需要执行某些操作,那么您必须自己测试.根据您的示例代码,在这种情况下不是这种情况.


Lef*_*ogh 5

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

  • 一切都是文件。

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

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

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

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

请考虑以下情形:

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

该文件名存储在变量中

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"
Run Code Online (Sandbox Code Playgroud)

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

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

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

filesexists.json  history20170728  SE-Data-API.pem  thisfolderexists
Run Code Online (Sandbox Code Playgroud)

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

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

0
Run Code Online (Sandbox Code Playgroud)

是的 魔法。

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

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

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

0
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

0
Run Code Online (Sandbox Code Playgroud)

因此该文件存在...

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

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

1
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)


FCA*_*A69 5

如果您使用 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
Run Code Online (Sandbox Code Playgroud)

“[ -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">
Run Code Online (Sandbox Code Playgroud)

  • `test` 和 `[` 是同义词。您也可以将“timeout”与“[”一起使用,如果 NFS 挂起,“test”也会冻结。 (2认同)