如果文件不存在,如何执行某些命令?

Dra*_*scu 9 shell file

我想检查文件是否存在,如果不存在,则创建它.

考虑以下C代码的等价物,但使用shell脚本.

if(!exist) {
    command;
    command;
}
else {
    command;
    command;
}
Run Code Online (Sandbox Code Playgroud)

Jos*_* R. 18

检查文件是否存在是一项非常常见的任务.要搜索相关问题,请使用搜索栏(右上角).我用术语"bash脚本文件存在" 得到了很多结果

在任何情况下,您需要test内置或其语义等价[ ]:

[ ! -e your_file ] && >your_file
Run Code Online (Sandbox Code Playgroud)

要么

test ! -e your_file && >your_file
Run Code Online (Sandbox Code Playgroud)

这首先testyour_file不(!)存在(-e),并创建它,如果是这样的话.

有关可以运行的不同测试(除了-e)之外的更多信息,您可以键入:

help -m test | less
Run Code Online (Sandbox Code Playgroud)

  • 您也可以使用短路评估,如`[-e your_file] || > your_file` (4认同)
  • 请注意`[!如果文件确实存在,但 `[ -e your_file ] || -e your_file ] && >your_file` 将以代码 1 退出 >your_file` 将始终以代码 0 退出。 (3认同)

Dav*_*nez 15

你可以用这个:

if [ ! -e "$file" ]; then
       touch file
else
        ...
fi


l0b*_*0b0 7

if [ ! -e "$path" ]
then
    touch -- "$path"
fi
Run Code Online (Sandbox Code Playgroud)

一个更简单的版本就是简单touch -- "$path"- 它创建文件(如果它不存在),只是更新访问和修改时间(如果它存在).该双破折号(--)确保即使以短划线开头,并且可以创建文件引号周围$path是必要的.


Ste*_*las 7

不要这样做,它不仅受竞争条件的限制,而且还要[ -e /path/file ]检查你是否可以stat(2)对文件进行检查,因此它会因为不同的原因而返回false,这不仅是因为文件不存在.

一个示例是不存在的文件的符号链接或您没有搜索权限的目录中的文件.

一个更好的方法是在这里使用正确的标志来进行open(2)系统调用,也就是说O_CREAT|O_EXCL.这样,open()如果文件尚未存在而失败,则必须先检查数百万个CPU时钟周期.

使用类似Bourne的shell:

if (set -C && : > "$file") 2> /dev/null; then
  print '%s\n' "$file has been created
else
  print '%s\n' "It hasn't, possibly because it was already there"
fi
Run Code Online (Sandbox Code Playgroud)

(set -C是启用O_EXCL标志).

另外,为什么要创建一个空文件?您可能希望在该文件中存储某些内容.然后,就这样做:

set -C
{
  echo blah
  other-commands that-generate-the-content
} > "$file"
Run Code Online (Sandbox Code Playgroud)

然后,只有当命令组file不存在时才执行该命令组(并且可以创建它).

如果要测试文件是否存在,请至少写入:

[ -e "$file" ] || [ -L "$file" ]
Run Code Online (Sandbox Code Playgroud)

要么

ls -d -- "$file" > /dev/null 2>&1
Run Code Online (Sandbox Code Playgroud)

如果你关心它可能是一个符号链接.如果文件确实存在但您无权对其进行验证,那么仍将返回false.


现在,如果您想要有关测试文件存在的更长且历史性的答案:

最初,该test命令(在它首次出现的Unix v7中)没有-e(也没有-h/ -L选项或-a一元)选项.

测试文件存在的方法是ls.ls(with -d)列出文件并报告错误(并返回错误的退出状态),如果由于某种原因无法查找文件.Unix最初没有符号链接,但是当它们被引入时,ls被修改为lstat(2)在文件而不是文件上执行stat(2).也就是说,如果符号链接ls返回有关符号链接文件本身的信息,而不是符号链接指向的路径上的文件.

test(又名[)用于测试文件"存在"的选项最初是在Korn shell test内置中引入的.那-a不是-e.-a可访问的(我相信),这是一个比现有更准确的术语.

我不知道何时或什么介绍-e,可能是POSIX.POSIX ,为了避免可能与二元运算符(for )混淆,-e选择了-a它.-a

在任何情况下,-a-e尝试stat(2)对文件,而不是lstat(2).那是:

[ -e "$file" ]
Run Code Online (Sandbox Code Playgroud)

相当于:

ls -Ld -- "$file" > /dev/null 2>&1
Run Code Online (Sandbox Code Playgroud)

所以,严格来说,它返回true,如果在测试做的时候,有可能解决的符号链接后查找路径,如果stat(2)失败了,失败的原因被忽略.

stat如果文件不存在(ENOENT),可能会失败,即文件不存在或存在但是是不存在的文件的符号链接,但也有很多其他原因.查看可能的错误代码,stat(2)给出了一些想法:

  • EACCESS:在路径解析期间(可以是任何路径组件和任何符号链接的路径),您没有一个目录组件的搜索权限(请注意,您可能仍然可以通过另一个路径访问该文件).
  • ELOOP:无法解决路径,因为太多的符号链接已经解决了.
  • ENOTDIR.例如on /etc/passwd/foo或它的符号链接.