我使用以下脚本查看文件是否存在:
1 2 3 4 5 6 7 8
| #!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo"File $FILE exists."
else
echo"File $FILE does not exist."
fi |
如果我只想检查文件是否不存在,要使用什么正确的语法?
1 2 3 4 5 6
| #!/bin/bash
FILE=$1
if [ $FILE does not exist ]; then
echo"File $FILE does not exist."
fi |
- 我发现这个bash条件语句列表非常有用。
- 作为一个非常懒惰的人,我通常会使用以下愚蠢的权宜之计:if [ -f $FILE ]; then; else; echo"File $FILE does not exist."; fi;可能很好,我发现了这个问题,并学会了以更恰当的方式来做。:)
- 要成为挂件,您应该说"常规文件",因为大多数UNIX/POSIX文档通常指所有类型的文件系统条目,一个简单的"文件",例如,符号链接是一个文件的类型,如命名管道、常规文件、目录、块特殊、字符特殊、套接字等。
- @kevinarpe如果你想测试一些东西是否存在,使用-e。-f不会拾取目录、符号链接等。
- 为了安全起见,请始终使用双引号来正确处理带空格的文件名,例如,FILE=$1->FILE="$1"和if [ -f $FILE ];->if [ -f"$FILE" ];。
- 不幸的是,这很容易出现在竞争条件下,在大多数用例中都不有用,除了一些简单的hello world示例。
- 作为补充说明,关于"$file"变量:按照惯例,环境变量(路径、编辑器、shell等)和内部shell变量(bash_版本、随机等)都是完全大写的。所有其他变量名都应为小写。由于变量名区分大小写,因此此约定避免意外地覆盖环境变量和内部变量。
- bash的可能副本:如何检查某些文件是否存在?
- @JWW这与那个问题相反。这要求特定的语法。
- @hek2mgl那么,正确的方法是什么?
- @Mateuszkonieczny它实际上取决于用例:读和/或写,共享访问与否。一个简单的例子是从文件中读取的程序。不是在启动程序之前检查文件是否存在(这是一个争用条件),而是可以使用文件名作为参数启动程序。如果文件不存在,程序将返回一个错误,该错误可以由调用脚本处理。但这实际上只是一个用例,一个例子。
test命令(这里是[)有一个"not"逻辑运算符,它是感叹号(类似于许多其他语言)。试试这个:
1 2 3
| if [ ! -f /tmp/foo.txt ]; then
echo"File not found!"
fi |
- 我费了点劲才找到"如果两个文件中没有任何一个不存在"的正确语法。以下两项工作:if [ ! \( -f"f1" -a -f"f2" \) ] ; then echo MISSING; fiif [ ! -f"f1" ] || [ ! -f"f2" ] ; then echo MISSING; fi。
- @大卫的内底更加多汁:[ -f /tmp/foo.txt ] || echo"File not found!"。
- 参数可以是以下任意一种:-e: Returns true value, if file exists-f: Return true value, if file exists and regular file-r: Return true value, if file exists and is readable-w: Return true value, if file exists and is writable-x: Return true value, if file exists and is executable-d: Return true value, if exists and is a directory。
- 如果要在if操作中使用2个条件,请使用-a运算符,这意味着和。我认为,如果您使用[[]]运算符,这也是可能的。
- 使用! -f与&&相比,使用-f与||存在不对称性。这与不存在检查返回的退出代码有关。如果您需要您的行始终使用退出代码0(有时您不需要这个约束)干净地退出,那么这两种方法是不可互换的。或者,只需使用一个if语句,您就不再需要担心不存在检查的退出代码了。
- 如果文件名是动态的,用if [ ! -f"$filename" ]; then...测试它,因为它可能包含空格。
- 使用它只在脚本存在的情况下运行cron作业,因为cron任务部署在应用程序代码库* * * * * [ -f foo.php] && php foo.php之前。
- [[是一个bash关键字,类似于(但比)命令。请参见和。除非您是为posix sh编写,否则建议使用[]。
- 在[和!之间保留一个space,否则不起作用。
- 我提议用[[ ! -f ... ]]; then。为什么不使用双括号?--我不能得到你的建议。
- [[内置比[快,后者需要bash进行外部调用。
bash文件测试
-b filename块特殊文件-c filename—特殊字符文件-d directoryname—检查目录是否存在-e filename—检查文件是否存在,无论文件类型(节点、目录、套接字等)-f filename—检查常规文件是否存在,而不是目录-G filename—检查文件是否存在,是否属于有效的组ID-G filename set-group-id—如果文件存在并且设置了组ID,则为真-k filename粘性钻头-L filename—符号链接-O filename—如果文件存在且由有效用户ID拥有,则为真。-r filename—检查文件是否可读-S filename—检查文件是否为socket-S filename—检查文件大小是否为非零-u filename—检查是否设置了文件集用户ID位-w filename—检查文件是否可写-x filename—检查文件是否可执行
如何使用:
1 2 3 4 5 6 7
| #!/bin/bash
file=./file
if [ -e"$file" ]; then
echo"File exists"
else
echo"File does not exist"
fi |
使用!运算符可以否定测试表达式。
1 2 3 4 5 6 7
| #!/bin/bash
file=./file
if [ ! -e"$file" ]; then
echo"File does not exist"
else
echo"File exists"
fi |
- @如果你愿意,你可以自由编辑我的帖子并将其添加到列表中。我想你的意思是:-n String—检查字符串的长度是否不为零。或者你是说file1 -nt file2-检查文件1是否比文件2新(你也可以用-ot来表示旧的文件)
- 我们的The unary operator -z tests for a null string, while -n or no operator at all returns True if a string is not empty.~ibm.com /。/图书馆/ L BASH的测试index.html
- 为什么不添加一类函数的一些函数exists(){???????"如果[美元] 1,"回声";然后"1元1元回波存在的人"不存在,"我"
可以用"!"来否定表达式。:
1 2 3 4 5 6 7
| #!/bin/bash
FILE=$1
if [ ! -f"$FILE" ]
then
echo"File $FILE does not exist"
fi |
相关的手册页是用于内置bash命令的man test或等效的man [或help test或help [。
- 在巴什,[是一个内置的。因此,相关信息是由help [获得的。但这表明,[是test内置的同义词,因此,相关信息是由help test获得的。另请参见手册中的bash条件表达式部分。
- @是的,但是bash内置的[命令的行为与外部的[命令非常相似,所以无论是man test还是man [都可以让您很好地了解它的工作方式。
- @除了bash内置的[比我系统上的外部命令[有更多的开关外,keitthththompson…一般来说,我认为最好阅读特定于给定工具的文档,而不是特定于另一个模糊相关工具的文档。我可能是错的,尽管;)
1 2
| [[ -f $FILE ]] || printf '%s does not exist!
'"$FILE" |
此外,该文件可能是一个断开的符号链接,或者是一个非常规文件,例如套接字、设备或FIFO。例如,要添加对断开符号链接的检查:
1 2 3 4 5 6 7 8 9
| if [[ ! -f $FILE ]]; then
if [[ -L $FILE ]]; then
printf '%s is a broken symlink!
'"$FILE"
else
printf '%s does not exist!
'"$FILE"
fi
fi |
- 我能问一下为什么这两个"["在考试中吗?(如)-一个$file)]我在一个Solaris设备上尝试了所有提到的选项,但只有一个有效,非常感谢,但是为什么呢?
- 双括号是一种"现代"扩展;例如,它们不会进行分词(例如对于带有空格的文件名),但仍然适用于空字符串:mywiki.wooledge.org/bashfaq/031
- 根据tldp.org/ldp/abs/html/fto.html,a在效果上与-e相同。它已被"否决",不鼓励使用。无论如何+1表示也要检查断开的符号链接
- @dimitrismistriotis two"["是zsh&bash;实现(不同)的不可移植扩展,一般情况下,如果可能,您应该避免使用它。
- 请参阅so 321348,了解单括号条件表达式中不能否定-a的原因。我建议完全避免使用-a。
- 我投了赞成票,因为它用了。它是一种广泛使用的扩展。如果您知道您正在使用bash,那么就没有理由不使用它。它比[]更不容易出错。
- 为了消除-a,稍微改变了一下,但也因为-a相当于-e,它对现有文件返回true,不管文件类型如何,如果在第二个示例中添加对fifos或socket的检查,就会遇到麻烦。
值得一提的是,如果需要执行单个命令,可以缩写
1 2 3
| if [ ! -f"$file" ]; then
echo"$file"
fi |
到
1
| test -f"$file" || echo"$file" |
或
1
| [ -f"$file" ] || echo"$file" |
我更喜欢使用与posix shell兼容的格式执行以下一行程序:
1 2 3
| $ [ -f"/$DIR/$FILE" ] || echo"$FILE NOT FOUND"
$ [ -f"/$DIR/$FILE" ] && echo"$FILE FOUND" |
对于几个命令,就像在脚本中一样:
1
| $ [ -f"/$DIR/$FILE" ] || { echo"$FILE NOT FOUND" ; exit 1 ;} |
一旦我开始这样做,我就很少使用完整类型的语法了!!
- 首先,未加引号的变量引用容易出错。也就是说,它在任何bash手册页中都说,[或test内置将在默认情况下测试参数的文件存在性(而不是-e)?那不是模棱两可的吗?afaik(和aiui"条件表达式"一节)唯一用您的方法测试的是,参数不是空的(或未定义的),在这种情况下,这是一个重言式(让$DIR = ''和$FILE = '',那么参数仍然是'//'。
- 证据:ls /foo,结果ls: cannot access /foo: No such file or directory。[ /foo ] && echo 42,结果42。GNUBash,版本4.2.37(1)-发行版(i486 PC Linux GNU)。
- @提示:在我写这个答案的时候,我没有指定-f选项。显然,如果您不确定它是一个常规文件,您可以始终使用-e。此外,在我引用这些构造的所有脚本中,我必须在没有足够的校对的情况下提交这些构造。
- ACK。但是,您可能知道,一行程序无法解决if-else问题:[ $condition ] && if_true || if_false很容易出错。无论如何,我发现[ ! -f"$file" ] && if_not_exists比[ -f"$file" ] || if_not_exists更容易阅读和理解。
要测试文件是否存在,参数可以是以下任意一个:
1 2 3 4
| -e: Returns true if file exists (regular file, directory, or symlink)
-f: Returns true if file exists and is a regular file
-d: Returns true if file exists and is a directory
-h: Returns true if file exists and is a symlink |
以下所有测试都适用于常规文件、目录和符号链接:
1 2 3 4
| -r: Returns true if file exists and is readable
-w: Returns true if file exists and is writable
-x: Returns true if file exists and is executable
-s: Returns true if file exists and has a size > 0 |
示例脚本:
1 2 3 4 5 6 7 8
| #!/bin/bash
FILE=$1
if [ -f"$FILE" ]; then
echo"File $FILE exists"
else
echo"File $FILE does not exist"
fi |
您可以这样做:
1
| [[ ! -f"$FILE" ]] && echo"File doesn't exist" |
或
1 2 3
| if [[ ! -f"$FILE" ]]; then
echo"File doesn't exist"
fi |
如果要同时检查文件和文件夹,请使用-e选项而不是-f。对于常规文件、目录、套接字、字符特殊文件、块特殊文件等,-e返回true。
- 这不是一个bash的特异性。你的语法是从Korn外壳还可在Zsh和Bash。它有优势的标准工具有限公司[这里虽然。
- (一)定期检查文件和目录的-f)是许多不同的只是两个类型的文件。的符号链接,也有插座的设备,管道,门……[ -e将测试文件(包括任何类型的经常性,先进先出,后链接目录…………………)的分辨率。
- "I Don’t stephanechazelas:任何地方国有企业或zsh凯驰(上海)标签。我们是在谈论什么是bash或最标准的UNIX系统上。所以,在特定的上下文,它的攻击。OP是不是需要知道每一个无论是去壳):D
- 这是在评论"重击你的答案部分特异性"。
- 内:是的,"stephanechazelas上下文(和标准bash Bash,SH),它的特异性。我看到你的评论中的第二点,这是完全从上下文。不需要-eOP T -f,他需要。
- jahid将军",呼唤构建特定的效用就一定是错的,只因为它不是攻击性的。如果能使用它在一个简单的凯驰(上海),然后它是一本实用的约束。事实上,这是在讨论这个话题的人在没有许可证的说,"顺便说一下,现在我们谈的重击,让我介绍你的东西,这是特定的攻击。在它的不是。1是在被misleading技术论坛。如果你是写作关于Python,你说,"现在,让我介绍你到这个惊人的特异性概念:ifPython语句。"?我不认为如此。
- 你也错过了马克与...you -e作评论。他说的是真的,-e收益几乎任何实体的文件系统:文件目录,规范,先进先出,特殊字符特殊文件块,文件等,您的回答是,"你suggest看来简单的扩大一点,在线目录和它的-f将定期对匹配的文件。你不是;它的宽比这多。
对于不带引号的变量运行test时应该小心,因为它可能会产生意外的结果:
1 2 3 4 5 6
| $ [ -f ]
$ echo $?
0
$ [ -f"" ]
$ echo $?
1 |
建议通常将测试变量用双引号括起来:
1 2 3 4 5 6 7
| #!/bin/sh
FILE=$1
if [ ! -f"$FILE" ]
then
echo"File $FILE does not exist."
fi |
- 建议将每个变量都用双引号括起来,除非您确切地知道您有一个不必要的罕见情况,或者有一个更罕见的有害情况。(不,这不是其中之一。)
- 你愿意详细说明为什么不使用双引号吗?否则我在评论中看不到有用之处。
- 我的意思是:这不是不必要或有害的罕见情况之一。shell程序员应该习惯于用双引号括住(几乎)每个变量;这个规则不局限于[ ... ]。
- 另请参见stackoverflow.com/questions/10067266/…
有三种不同的方法可以做到这一点:
用bash否定退出状态(没有其他答案这样说):
1 2 3
| if ! [ -e"$file" ]; then
echo"file does not exist"
fi |
或:
1
| ! [ -e"$file" ] && echo"file does not exist" |
否定测试命令[中的测试(这是之前给出的大多数答案的方式):
1 2 3
| if [ ! -e"$file" ]; then
echo"file does not exist"
fi |
或:
1
| [ ! -e"$file" ] && echo"file does not exist" |
根据试验结果为阴性(||而不是&&进行试验):
只有:
1
| [ -e"$file" ] || echo"file does not exist" |
这看起来很愚蠢(imo),除非您的代码必须可移植到Bourne Shell(如Solaris 10或更早版本的/bin/sh),而缺少管道否定运算符(!)。
1 2 3 4 5
| if [ -e"$file" ]; then
:
else
echo"file does not exist"
fi |
- 可移植性之间的差异和[ !! [任何吗?
- 该管道是一! [POSIX外壳(或命令)Otherwise, the exit status shall be the logical NOT of the exit status of the last command2.9.2和[ ! POSIX OS是一个测试是! expression True if expression is false. False if expression is true.,POSIX,和在我的经验,无论是extensively负载。
- frozenflame The Bourne shell",才有了这!关键字是由Korn外壳。除了也许是Solaris 10和旧的,你不太可能吃到过,不过这些天,Bourne外壳。
在 </P >
在[命令不一stat()(不lstat())的系统调用的路径可存储在$file时返回true,如果和系统调用succeeds和类型的文件为returned用stat()是"正常的"。 </P >
所以,如果[ -f"$file" ]时返回true,你可以告诉该文件是否存在和是一个正常的文件或一个符号,一个正则正则resolving文件(或至少是在时间的stat())。 </P >
但是如果它时返回false(或如果[ ! -f"$file" ]或! [ -f"$file" ]返回true),是有很多不同的可能性: </P >
- 该文件不存在。
- 在file exists,但是,是不是一个正常的文件(可以是一个设备,先进先出(FIFO),目录,插座…………………)
- 在file exists,但你没有搜索到父目录的权限
- "但那file exists路径来访问它是太长
- 该文件是一个符号,一个正常的文件,但你没有寻找到一些权限的目录参与的分辨率的符号。
- …………………任何其他的理由,如《stat()系统调用可能失败。
在短的,它应该是: </P >
1 2 3 4 5 6 7 8 9 10 11 12 13
| if [ -f"$file" ]; then
printf '"%s" is a path to a regular file or symlink to regular file
'"$file"
elif [ -e"$file" ]; then
printf '"%s" exists but is not a regular file
'"$file"
elif [ -L"$file" ]; then
printf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not
'"$file"
else
printf 'I cannot tell if"%s" exists, let alone whether it is a regular file or not
'"$file"
fi |
知道这悲伤的方法中的文件不存在的,我们会需要的stat()系统调用与返回的错误代码ENOENT(美国的一个ENOTDIRtells的多径分量的是不是一个目录是在另一个案例,我们可以告诉该文件不存在,通过T路径)。不幸的[T命令不让我们知道。它将返回错误代码中的错误是否是enoent,eaccess(权限拒绝enametoolong),或任何其他的。 </P >
在[ -e"$file" ]试验也可以被用做ls -Ld --"$file"> /dev/null。。。。。。。在这情况下,ls会告诉你为什么在stat()失败,虽然在信息不易被用于以编程方式: </P >
1 2 3 4 5 6
| $ file=/var/spool/cron/crontabs/root
$ if [ ! -e"$file" ]; then echo does not exist; fi
does not exist
$ if ! ls -Ld --"$file"> /dev/null; then echo stat failed; fi
ls: cannot access '/var/spool/cron/crontabs/root': Permission denied
stat failed |
至少lstells我们这不是因为文件不存在,它fails T。。。。。。。这是因为它不能告诉是否在file exists或不。在[命令是不容忽视的问题。 </P >
与zsh壳,你可以查询中的错误代码与$ERRNO特殊变量在书中[命令,和解码-12864LCD那号码使用$errnos特殊阵列中的zsh/system模块: </P >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| zmodload zsh/system
ERRNO=0
if [ ! -f"$file" ]; then
err=$ERRNO
case $errnos[err] in
("") echo exists, not a regular file;;
(ENOENT|ENOTDIR)
if [ -L"$file" ]; then
echo broken link
else
echo does not exist
fi;;
(*) syserror -p"can't tell:""$err"
esac
fi |
(beware的$errnos支持是破碎的版本与一些大学本科zsh当与最近的版本中gcc)。 </P >
要反转测试,请使用"!".这相当于其他语言中的"非"逻辑运算符。试试这个:
1 2 3 4
| if [ ! -f /tmp/foo.txt ];
then
echo"File not found!"
fi |
或者用稍微不同的方式写:
1 2 3
| if [ ! -f /tmp/foo.txt ]
then echo"File not found!"
fi |
或者你可以使用:
1 2 3
| if ! [ -f /tmp/foo.txt ]
then echo"File not found!"
fi |
或者,一起预测:
1
| if ! [ -f /tmp/foo.txt ]; then echo"File not found!"; fi |
可写为(使用then"和"operator:&;&;)如下:
1
| [ ! -f /tmp/foo.txt ] && echo"File not found!" |
看起来比这短:
1
| [ -f /tmp/foo.txt ] || echo"File not found!" |
此代码也有效。
1 2 3 4 5 6 7
| #!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo"File '$FILE' Exists"
else
echo"The File '$FILE' Does Not Exist"
fi |
江户十一〔五〕事也算在内。它对我有效(基于bash shell:检查文件是否存在):
1
| test -e FILENAME && echo"File exists" || echo"File doesn't exist" |
最简单的方法
1 2
| FILE=$1
[ ! -e"${FILE}" ] && echo"does not exist" || echo"exists" |
此shell脚本还可用于在目录中查找文件:
1 2 3 4 5 6 7 8 9 10
| echo"enter file"
read -r a
if [ -s /home/trainee02/"$a" ]
then
echo"yes. file is there."
else
echo"sorry. file is not there."
fi |
- 不清楚这是否会增加其他答案尚未给出的内容。它硬编码一个路径名。因为这个问题被标记为bash,所以它可以使用read -p"Enter file name:" -r a来提示和读取。它确实在变量周围使用了引号;这很好,但应该解释一下。如果回送文件名可能会更好。这检查文件是否存在且不是空的(这是-s的意思),而问题是询问任何文件是否为空(-f更合适)。
有时它可能会得心应手的使用&;&;和| |经营者。 </P >
状细胞(如果你已经命令"测试"): </P >
1
| test -b $FILE && echo File not there! |
或 </P >
1
| test -b $FILE || echo File there! |