如何在不知道文件名但知道其扩展名的情况下使用 shell 脚本读取文件

How to read a file without knowing its name but knowing its extension using shell script

我正在尝试更改我的代码以从目录中读取 .txt 文件。该目录只包含一个 .txt 文件,但我事先不知道它的名字。我只知道它是一个 .txt 文件。是否可以使用 shell 脚本来做到这一点?

下面是我当前读取文件的代码,但我必须手动指定文件名。

#!/bin/bash

declare -a var

filename='file.txt'
let count=0

while read line; do
    var[$count]=$line
    ((count++))
done < $filename

你可以用这个。 head 命令用于此上下文以确保一个结果。

filename=$(ls *.txt | head -n 1)

如果您 100% 确定只有一个匹配文件,只需替换:

done < $filename

作者:

done < *.txt

当然,如果您有零个或多个匹配文件,这将失败。因此,最好先进行测试。例如:

tmp=$(shopt -p nullglob || true)
shopt -s nullglob
declare -a filename=(*.txt)
if (( ${#filename[@]} != 1 )); then
  printf 'error: zero or more than one *.txt file\n'
else
  declare -a var
  let count=0
  while read line; do
    var[$count]=$line
    ((count++))
  done < "${filename[0]}"
fi
eval "$tmp"

shopt东东将nullglob选项的当前状态存储在变量tmp中,启用选项,最后恢复初始状态。如果存在 *.txt 文件为零的风险,则需要在此处启用 nullglob。没有 nullglob 会将文字字符串 *.txt 存储在数组 filename.

您的循环可以稍微优化一下:

  declare -a var
  while IFS= read -r line; do
    var+=("$line")
  done < "${filename[0]}"
需要

IFS= 来保留读取行中的前导和尾随空格。如果这不是您想要的,请将其删除。 read-r 选项在读取行中保留反斜杠。如果这不是您想要的,请将其删除。 += 赋值自动在索引数组的末尾添加一个元素。不用数了。如果您想知道您的数组包含多少元素,只需使用 ${#var[@]} 就像我们测试 filename 数组的长度一样。

请注意,如果您的 bash 版本足够新,则最好使用 mapfile 将文本文件的内容存储在 bash 数组中。例如,参见

也可以在赋值中触发参数扩展!

filename=$(echo -n *.txt)

如果你想万无一失(捕获匹配文件数不为1的情况),分配给一个数组并检查它的大小:

farr=( *.txt )
if (( ${#farr[*]} != 1 ))
then
  echo You lied to may when you said that there is exactly on .txt file
else
  filename=${farr[0]}
fi