【问题标题】:bash: processing (recursively) through all files in a directorybash:处理(递归)目录中的所有文件
【发布时间】:2010-12-11 21:07:40
【问题描述】:

我想编写一个 bash 脚本,它(递归地)处理特定类型的所有文件。

我知道我可以通过使用 find 得到匹配的文件列表:

找到 . -name "*.ext"

我想在脚本中使用它:

  1. 递归获取具有给定扩展名的文件列表
  2. 获取完整的文件路径名
  3. 将完整路径名传递给另一个脚本
  4. 检查脚本的返回码。如果非零,则记录无法处理的文件的名称。

我的第一次尝试看起来(伪代码)如下:

ROOT_DIR = ~/work/projects
cd $ROOT_DIR
for f in `find . -name "*.ext"`
do
    #need to lop off leading './' from filename, but I havent worked out how to use
    #cut yet
    newname = `echo $f | cut -c 3
    filename = "$ROOT_DIR/$newname"

    retcode = ./some_other_script $filename

    if $retcode ne 0
       logError("Failed to process file: $filename")
done

这是我第一次尝试编写 bash 脚本,所以上面的 sn -p 不太可能运行。但希望我尝试做的逻辑足够清晰,有人可以展示如何连接这些点并将上面的伪代码转换为工作脚本。

我在 Ubuntu 上运行

【问题讨论】:

  • 如果你使用'find $ROOT_DIR -name "*.exe"',你就不需要摆弄前导'./'。

标签: bash ubuntu


【解决方案1】:
find . -name '*.ext' \( -exec ./some_other_script "$PWD"/{} \; -o -print \)

【讨论】:

  • +1 很好的解决方案,我不知道你可以这样使用 -o。唯一的问题是有时(不是这里)您需要调用函数而不是外部可执行文件。
  • 嗯,这很神秘……(让我想起了 Perl!)。我不明白这一点。文件名是如何传递给另一个脚本的,我怎么知道脚本是否返回非零,所以我知道要做什么?
  • @skyeagle:-exec 谓词中的{} 指示注入当前匹配的位置。 -exec 谓词本身测试命令的结果代码,如果为 0,则为 true,否则为 false。
【解决方案2】:

使用| while read 遍历文件名是可以的,只要没有需要处理运营商退货的文件:

find . -name '*.ext' | while IFS=$'\n' read -r FILE; do
  process "$(readlink -f "$FILE")" || echo "error processing: $FILE"
done

【讨论】:

  • 我不会说官方完全不鼓励它。比for f in $(find)好多了。如果文件名中有空格、制表符或换行符,可能会出现问题。可以这样改进:while IFS=$'\n' read -r FILE
  • @Dennis,我现在找不到该页面(可能不是官方的),但不鼓励使用“while | read”,因为运营商返回是文件的有效字符(幸运的是没有人使用它们)。添加了您的建议。
  • 这样的假设总是有问题的。即使“普通”用户经常避免文件名中的换行符,但这并不意味着没有人这样做——攻击者肯定会这样做。任何程序都应该努力接受所有允许的文件名;幸运的是,这在每一种真正的编程语言中都很容易——这是避免使用 shell 脚本的另一个原因。
  • @Philipp:嗯,这是一个更笼统的讨论。我不会将 shell 语言称为“非真实编程语言”,但它们确实有其缺点和历史包袱。但是,恕我直言,他们设计了有史以来最强大的编程概念之一:管道。
  • 也许你在想this page。很好地讨论了文件名带来的挑战。
猜你喜欢
  • 2013-08-28
  • 1970-01-01
  • 2011-12-24
  • 1970-01-01
  • 2013-05-17
  • 1970-01-01
  • 2016-07-06
  • 2012-11-06
相关资源
最近更新 更多