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])
。 - 要包含隐藏文件,请添加
D
glob 限定符 - 在某些语言环境中(包括 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
)。
由于文件名通配模式已扩展为按字典顺序排序的列表,因此您将获得第一个名称。