如何在Bash中检查文件是否为空?

329

我有一个文件名为 diff.txt。我想要检查它是否为空。

我写了一个类似下面的bash脚本,但是我无法让它工作。

if [ -s diff.txt ]
then
        touch empty.txt
        rm full.txt
else
        touch full.txt
        rm emtpy.txt
fi

47
[-s FILE] 如果FILE存在且大小大于零,则返回True。 因此,如果“diff.txt”不为空,则会得到“empty.txt”。 - Matthias
3
PS:如果您想检查实际的diff调用,请检查返回值:if diff foo.txt bar.txt; then echo 'No difference' - l0b0
38
测试结果可以被否定:if [ ! -s diff.txt ]; then echo "为空"; else echo "有内容"; fi - David Ramirez
1
注意末尾的换行符。使用 $ cat diff.txt | hexdump -C 命令检查文件。 - Alejandro Blasco
@DavidRamirez:请注意,[ … ] 与 bash 的本地 [[ … ]] 不同,后者允许一些会破坏前者的事情。例如,在引用或比较运算符方面。 - anon
12个回答

398

可以试试这个:

#!/bin/bash -e

if [ -s diff.txt ]; then
        # The file is not-empty.
        rm -f empty.txt
        touch full.txt
else
        # The file is empty.
        rm -f full.txt
        touch empty.txt
fi

顺便提一下,我已经按照@Matthias的建议交换了empty.txtfull.txt的角色。

13
外壳可以帮助纠正拼写错误。 empty=empty.txt; full=full.txt; diff=diff.txt; 如果 [ -s ${diff?} ]; then r=${empty?} t=${full?}; else r=${full?} t=${empty?}; fi; rm ${r?}; touch ${t?} - William Pursell
4
使用 Shellcheck 工具可以很好地发现拼写错误。 - Yokai
1
如果文件不存在,这肯定会失败,对吧?这只是用来检查文件是否为空的。 - geedoubleya
2
你也可以使用 set -u - Jon McClung
2
在这里shebang中传递的“-e”参数是什么? - Yatharth7
显示剩余6条评论

125
[ -s file.name ] || echo "file is empty"

22
[[ -s file.name ]] && echo "full" || echo "empty"如果文件名为file.name的文件存在且不为空,则输出"full",否则输出"empty"。 - McPeppr
1
[[ -s file.name ]] || { [[ -f file.name ]] && echo 'empty' || echo 'does not exist'; } - smarber
3
@smarber 对于像这样的简单检查,请使用 [ ... ] 而不是 [[ ... ]]。后者是 bashism,仅应用于不兼容的 bash 检查(例如 regexp)。如果您有机会编写任何需要遵循 POSIX shell portable 的内容(例如 Debian 系统脚本),那么你自己也会感谢这个习惯的 :). - pevik

79

[ -s file ] # 检查文件大小是否大于0

[ -s diff.txt ] && echo "file has something" || echo "file is empty"
如果需要,这将检查当前目录中所有的*.txt文件,并报告所有空文件:
for file in *.txt; do if [ ! -s $file ]; then echo $file; fi; done

4
不需要执行 $(ls *.txt,事实上也不应该这样做。有些人会将 ls 的默认设置用于长格式(比如我),而且 Shell 已经可以自己展开 *.txt。所以只需要执行 for file in *.txt 就可以了。 - PrincessRTFM
不错!如果您想递归检查所有txt文件,可以像这样使用“find”: for file in $(find . -name '*.txt'); do if [[ ! -s $file ]]; then echo $file; fi; done - KlimczakM

25

要检查文件是否为空或只包含空格,您可以使用grep:

if [[ -z $(grep '[^[:space:]]' $filename) ]] ; then
  echo "Empty file" 
  ...
fi

6
这是唯一正确的答案,应该被采纳。使用“-s”并不能回答问题。它寻找一个存在且大小大于0字节的文件。 - Akito

19
虽然其他答案是正确的,但是使用 -s 选项也会在文件不存在的情况下显示文件为空。通过添加额外的检查 -f 来先检查该文件是否存在,我们可以确保结果的正确性。
if [ -f diff.txt ]
then
  if [ -s diff.txt ]
  then
    rm -f empty.txt
    touch full.txt
  else
    rm -f full.txt
    touch empty.txt
  fi
else
  echo "File diff.txt does not exist"
fi

17

检查文件是否为空的最简单方法:

if [ -s /path-to-file/filename.txt ]
then
     echo "File is not empty"
else
     echo "File is empty"
fi

您也可以在一行上编写它:

您也可以在单行上编写:

[ -s /path-to-file/filename.txt ] && echo "File is not empty" || echo "File is empty"

10
@Jon Skeet's answer.

if [[ -f diff.txt && -s diff.txt ]]
then
  rm -f empty.txt
  touch full.txt
elif [[ -f diff.txt && ! -s diff.txt ]]
then
  rm -f full.txt
  touch empty.txt
else
  echo "File diff.txt does not exist"
fi

7
[[ -f filename && ! -s filename ]] && echo "filename exists and is empty"

3
许多答案是正确的,但我觉得它们可以更加完整/简单化等。例如: 示例1:基本if语句
# BASH4+ example on Linux :

typeset read_file="/tmp/some-file.txt"
if [ ! -s "${read_file}" ]  || [ ! -f "${read_file}" ] ;then
    echo "Error: file (${read_file}) not found.. "
    exit 7
fi

如果$read_file为空或不存在,则使用exit停止展示。我曾多次错误地将这里的顶部答案误解为相反的意思。

例2:作为函数

# -- Check if file is missing /or empty --
# Globals: None
# Arguments: file name
# Returns: Bool
# --
is_file_empty_or_missing() {
    [[ ! -f "${1}" || ! -s "${1}" ]] && return 0 || return 1
}

1

@noam-manos基于grep的答案类似,我使用cat解决了这个问题。对于我来说,-s无法工作,因为我的“空”文件大小大于0字节。

if [[ ! -z $(cat diff.txt) ]] ; then
    echo "diff.txt is not empty"
else
    echo "diff.txt is empty"
fi

测试值未加引号。如果diff.txt包含例如'x']] && rm -rf /home;#,那么这不会导致大问题吗? - Evi1M4chine
测试值未加引号。如果diff.txt包含例如'x' ]] && rm -rf /home; #,这不会导致大问题吗? - anon

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