【问题标题】:Linux bash script: Recurisely delete files if empty based on file format from user input [duplicate]Linux bash脚本:如果根据用户输入的文件格式为空,则递归删除文件[重复]
【发布时间】:2017-09-28 09:07:04
【问题描述】:

正如标题所描述的,我想递归地删除所有与用户给出的命名模式匹配的文件,但前提是文件为空。这是我的尝试:

#!/bin/bash

_files="$1"
[ $# -eq 0 ] && { echo "Usage: $0 filename"; exit 1; }
[ ! -f "$_files" ] && { echo "Error: $0 no files were found which match given naming structure."; exit 2; }
for f in $(find -name $_files)
do

    if [ -s "$f" ] 
    then
        echo "$f has some data."
            # do something as file has data
    else
        echo "$f is empty. Deleting file."
        rm $f
    fi
done

示例输出:

./remove_blank.sh *.o*
./Disp_variations_higher_0.o1906168 has some data.
./remove_blank.sh *.e*
./Disp_variations_higher_15.e1906183 is empty. Deleting file.

如您所见,代码有效,但一次只能用于一个文件。应该是一个相对简单的修复来让它工作,但我对 bash 脚本非常陌生,似乎无法弄清楚。对不起这个noobish问题。我做了一些研究以找到答案,但没有找到我真正需要的东西。提前感谢您的帮助。

编辑 我找到了两种不同的解决方案。正如@David Z 的建议,可以通过首先删除脚本的错误检查部分以及在 find 函数中的 $_files 变量周围加上引号来解决此问题。那么代码如下所示:

#!/bin/bash
_files=$1
[ $# -eq 0 ] && { echo "Usage: $0 filename"; exit 1; }
for f in $(find -name "$_files")

    if [ -s $f ] 
    then
        echo "$f  has some data."
        # do something as file has data
    else
        echo "$f is empty. Deleting file."
        rm $f
    fi

完成

或者,也可以简单地将 for 循环更改为 for f in "$@",这样可以将错误检查保留在脚本中。我不确定哪种方法更好,但如果我发现会再次更新。

【问题讨论】:

  • 你需要在任何地方引用命令行参数和$_files以防止扩展。
  • 您不能在一个find 命令中执行此操作吗?
  • filesrecursive 在 bash 问题中关联时,显而易见的答案应该是 find
  • 有点隐蔽,但我在正文第4行使用了find模块:for f in $(find -name $_files)
  • 我会期待像find -name $_files -empty -delete

标签: linux bash


【解决方案1】:

看起来就像您调用脚本的方式一样,shell 在运行脚本之前扩展了模式。例如,在

./remove_blank.sh *.o*

shell 将*.o* 转换为与该模式匹配的文件名列表,然后它实际运行的内容类似于

./remove_blank.sh Disp_variations_higher_0.o1906168 other_file.o12345 ...

但您只检查脚本中的第一个参数,因此最终会被删除。

解决方案:在运行脚本时引用模式。

./remove_blank.sh '*.o*'

您还需要删除测试[ ! -f "$_files" ] ...,因为$_files 被设置为模式(例如*.o*),而不是文件名。事实上,您可能想要重命名变量以使其清楚。最后,您需要在 find 命令中引用变量,

... $(find -name "$_files") ...

这样模式就可以一直到find,而不会被shell转换成文件名。

脚本还有一些其他问题,但您可能想在Code Review 上询问这些问题。我在这里确定的只是让它工作的最低要求。


顺便说一句,您可以使用find 本身来完成整个任务,这至少可以提供更简洁的代码:

find -name "$_files" -type f -empty -delete

【讨论】:

  • 我尝试了您的建议,但它抛出错误消息:错误:./remove_blank.sh 找不到与给定命名结构匹配的文件。来自输入: ./remove_blank.sh '.o' 是的,我确保运行脚本的目录中有 .o 文件。
  • 啊,对,我会更新以澄清这一点。
  • 大卫成功了,谢谢。但是我确实找到了一个替代品,它可以让我保持错误检查。根据本文的建议,我只需将for f in $(find -name "$_files") 行替换为for f in "$@"stackoverflow.com/questions/19458104/… 这两种方法是否有任何利弊权衡?
猜你喜欢
  • 2015-07-06
  • 1970-01-01
  • 2014-10-28
  • 2021-12-24
  • 2019-09-02
  • 1970-01-01
  • 1970-01-01
  • 2015-05-27
  • 2012-12-20
相关资源
最近更新 更多