循环遍历bash中扩展名为.txt的所有文件

时间:2018-05-04 10:46:27

标签: bash shell

我正在尝试遍历文件夹中的文件并测试.txt扩展名。 但是我收到以下错误:“awk:无法打开=(没有这样的文件或目录)

这是我的代码:

!/bin/bash

files=$(ls);
for file in $files
  do
  # extension=$($file | awk -F . '{ print $NF }');
  if [ $file | awk -F . "{ print $NF }" = txt ]
    then
      echo $file;
    else
      echo "Not a .txt file";
  fi;
done;

1 个答案:

答案 0 :(得分:6)

你这样做的方式在很多方面都是错误的。

  1. 您永远不应解析ls的输出。它不直观地处理包含特殊字符的文件名请参阅Why you shouldn't parse the output of ls(1)
  2. 不要使用变量来存储多行数据。变量中ls的输出预计会进行单词拆分。在您的情况下,files被引用为普通变量,并且没有分隔符集,您无法查看存储的多个文件。
  3. 此处绝对不需要使用awk,部分$file | awk -F . "{ print $NF }" = txt完全错误,您没有将file的名称传递给管道,只传递变量$file,应该是echo "$file"
  4. 如果您计划将其作为可执行文件(即#!/bin/bash)运行,则右侧解释器she-bang应该已在脚本中设置为./script.sh。更推荐的方法是说#!/usr/bin/env bash让shell识别安装的bash的默认版本。
  5. 因此,您的要求可以简单地缩减为

    for file in *.txt; do
        [ -f "$file" ] || continue
        echo "$file"
    done
    

    这是一个使用*.txt的glob模式的简单示例,该模式对以txt格式结尾的所有文件进行路径名扩展。在处理循环之前,将glob作为文件列表进行扩展,即假设文件夹中的文件为1.txt2.txtfoo.txt,则生成循环

    for file in 1.txt 2.txt foo.txt; do
    

    即使存在没有文件,即当glob匹配为空(没有找到文本文件)时,条件[ -f "$file" ] || continue将通过检查glob是否返回任何有效文件结果或仅仅确保循环正常退出未展开的字符串。如果除了有效的文件参数之外,条件[ -f "$file" ]将失败。

    或者,如果您再次为bourne定位脚本shell,请启用glob选项以删除不匹配的glob,而不是保留它们

    shopt -s nullglob
    for file in *.txt; do
        echo "$file"
    done
    

    使用shell数组存储glob结果的另一种方法,稍后解析它们以对它们执行特定操作。在将文件列表作为另一个命令的参数列表时,这种方法很有用。使用正确的引用扩展"${filesList[@]}"将保留文件名中的间距/制表符/换行符和其他元字符。

    shopt -s nullglob
    filesList=(*.txt)
    
    for file in "${filesList[@]}"; do
        echo "$file"
    done