bash 获取目录中的第一个文件

bash 获取目录中的第一个文件

bash 如何获取目录中的第一个文件?首先是 shell glob 首先找到的内容。

我在 bash 中寻找目录中的第一个文件时,发现了一个旧帖子有一个非常具体的要求。我想为后代记录我对一般问题的解决方案,并为人们提供一个地方来放置他们想要分享的替代解决方案。

答案1

要获取当前目录中的第一个文件,您可以将扩展放入数组中并获取第一个元素:

files=(*)
echo "${files[0]}"
# OR
echo "$files" # since we are only concerned with the first element

假设您当前的目录包含多个目录,您可以循环遍历并获取第一个文件,如下所示:

for dir in *; do
    files=($dir/*)    
    echo "${files[0]}"
done

但请注意,根据您的 shell 设置,files=(*)如果没有文件,可能会返回一个包含一个元素(即“*”)的数组。因此,您必须检查数组中的文件名是否与实际存在的文件相对应(并记住这*是一个有效的文件名)。

答案2

所有现有的答案似乎首先创建目录的完整列表,这可能需要一段时间才能包含数千个元素,所以我最终得到了简单的结果:

ls -AU | head -1

其中-U意味着未排序,因此会立即产生结果。

答案3

zsh

  • 区域设置排序顺序中的第一个非隐藏文件:first=(*(N[1]))
  • 相同,但仅限于非目录文件:first=(*(N^/[1]))
  • 相同,但也不包括目录的符号链接:first=(*(N^-/[1]))
  • 限制于常规的文件:first=(*(N.[1]))
  • 相同,但包括常规文件的符号链接:first=(*(N-.[1]))

更多注意事项:

  • 这些定义了一个大批变量,因为它仍然需要能够存储多变的元素数量:0(无匹配文件)或1(匹配文件,其中仅选择第一个)。要改为定义$first标量变量(如果没有匹配文件,则让它包含空字符串),您可以(){ first=$1; } *(N[1])这样做。或者$first,如果没有匹配的文件,则保持标量变量不变: (){ (($#)) && first=$1; } *(N[1])
  • 要包含隐藏文件,请添加Dglob 限定符
  • 在某些语言环境中(包括 2020 年起在 GNU 系统上通常使用的大多数语言环境,例如en_US.UTF-8),排序规则并不总是确定的,因为某些字符排序相同。例如参见之后touch

答案4

要获取目录中排在第一位的常规文件的名称,您可以使用

shopt -s nullglob dotglob
unset -v name

for name in some/path/*; do
    [ -f "$name" ] && break
    unset -v name
done

在此循环之后,$name要么是首先排序的常规文件的名称,要么如果目录中没有常规文件,则该变量将被取消设置some/path

这里使用的 shell 选项确保如果模式不匹配 ( nullglob) 则不会运行循环,并且我们还匹配隐藏名称 ( dotglob)。

由于文件名通配模式已扩展为按字典顺序排序的列表,因此您将获得第一个名称。

相关内容