循环子目录中包含句点的文件名,但排除路径和文件扩展名

循环子目录中包含句点的文件名,但排除路径和文件扩展名

我在目录中有一个 bash 脚本./。该目录包含目录output.其中output有文件,例如...

Alabama.txt
U.S. Virgin Islands.txt

如何循环遍历文件output并打印以下输出

Alabama
U.S. Virgin Islands

答案1

for pathname in output/*.txt; do
    basename "$pathname" .txt
done

basename实用程序获取路径名并从中删除所有目录部分,只留下最终的文件名部分。它还接受一个字符串作为可选的第二个参数。该字符串将从给定路径名的末尾被修剪掉。

我们basename在所有名称匹配的循环中使用output/*.txt来删除output/路径名的一部分并删除.txt文件名后缀。这仅留下输出的文件名的“茎”。

您可以使用内置标准参数替换来实现相同的效果:

for pathname in output/*.txt; do
    name=${pathname#output/}
    printf '%s\n' "${name%.txt}"
done

这对扩展为的每个路径名执行两个参数替换output/*.txt;一个用于删除初始output/子字符串,第二个用于删除尾随子.txt字符串。

output如果存在目录中可能没有带有文件名后缀的文件的风险.txt,那么您可能需要设置nullglobshell 选项(使用shopt -s nullglob)。这将阻止上述循环运行一次,否则它们会执行一次(使用output/*.txt中的未扩展模式$pathname)。

dotglob如果您想匹配目录中的隐藏名称,您可能还需要设置shell 选项。

答案2

zsh而不是bash

print -rC1 -- output/*.*(N:t:r)

其中,在olumn上print -rC1 --打印其参数raw ,并且是 glob 限定符,用于启用(如果没有匹配文件,则 glob 将扩展为空),是类似 csh 的修饰符,用于获取文件的ail 和oot(删除目录部分)和扩展)。1 C(N:t:r)Nnullglob:t:rtr

D 如果您还想包含隐藏文件,请添加glob 限定符(在这种情况下,您可能需要更改*.*?*.*以确保这些隐藏文件具有扩展名。

使用任何 shell,但使用 的 GNU 实现basename,并假设您感兴趣的所有文件都没有隐藏并且具有.txt扩展名,output其中至少包含一个这样的文件,并且文件列表不太大,以免要超过execve()args+env 的大小限制,您还可以执行以下操作:

basename -as.txt output/*.txt

特别是对于bash(GNU shell),以及使用 的 GNU 实现sed,您还可以执行以下操作:

(
  shopt -s dotglob nullglob
  printf '%s\0' output/?*.* |
    LC_ALL=C sed -z 's:.*/::; s/\.[^.]*$//' |
    tr '\0' '\n'
)

zsh包含隐藏文件的近似值。

相关内容