【问题标题】:List of extensions of filenames in bash script in one line一行中的 bash 脚本中文件名的扩展名列表
【发布时间】:2018-12-04 02:09:48
【问题描述】:

我目前有以下代码行:

ls /some/dir/prefix* | sed -e 's/prefix.//' | tr '\n' ' '

这确实实现了我想要它做的事情:

  • 获取前缀开头的文件列表
  • 从每个字符串中删除路径和前缀
  • 删除换行符并替换为空格以供以后处理。

例如:

/some/dir/prefix.hello
/some/dir/prefix.world

应该变成

hello world

但我觉得有更好的方法来做到这一点。有没有更好的方法在一行中做到这一点?

【问题讨论】:

  • 您似乎不仅删除了prefix,还删除了下一个字符。这就是你想要的吗?
  • @BenjaminW。是的,前缀和.,我基本上想要文件扩展名列表。
  • 所以,一个字面句号,对吧?
  • 您需要使用ls 程序,echo 不需要吗?

标签: bash sed filenames ls tr


【解决方案1】:

这是一个仅使用内置函数的两行代码:

fnames=(some/dir/prefix*)
echo "${fnames[@]##*.}"

这就是它的工作原理:

  • fnames=(some/dir/prefix*) 创建一个包含所有以prefix 开头的文件的数组,并避免解析ls 带来的所有问题
  • echo "${fnames[@]##*.}" 是两个参数扩展的组合:${fnames[@]} 打印所有数组元素,##*. 部分从每个数组元素中删除以 . 结尾的任何最长匹配项,只留下扩展名

如果您一心想要单线,只需将两个命令与&& 连接起来。

【讨论】:

  • 根据此处的建议避免使用 ls,您的解决方案更具可读性,因此我将其标记为已接受,谢谢!
  • 非常简单好用。
【解决方案2】:

不建议将ls 输出传递给外部程序,以下 bash 解决方案可能对您有所帮助。

for file in prefix*; do echo ${file##*.}; done

现在也添加非单线形式的解决方案。

for file in prefix*
do
   echo ${file##*.}
done

【讨论】:

  • 不过,这会每行打印一个文件,并且对于 /path/.has/period/prefix.ext 之类的内容会失败,因为它会删除 *. 的最短匹配项。
  • @BenjaminW.,感谢您告诉我,忽略了它,现在添加它。
【解决方案3】:

这是一个非常简单的 Awk 单行代码来实现这一点:

awk -F. '{$0=FILENAME; printf $NF" "; nextfile}' /some/dir/prefix*

它基本上做了以下事情:

  • -F.:将字段分隔符FS 设置为.。这样$NF 代表扩展。
  • $0=FILENAME:忽略当前记录并将其设置为FILENAME,以这种方式重新解析所有内容。
  • print $NF; nextfile :打印扩展名并转到下一个文件。

这样做的问题是文件仍然读取当前文件的记录。如果该文件为空,则会失败。

要使用空文件,您可以使用gawk 扩展名BEGINFILE

awk -F. 'BEGINFILE{$0=FILENAME; printf $NF" "; nextfile}' /some/dir/prefix*

或者你可以遍历所有参数:

awk -F. 'BEGIN{for(i in ARGV){$0=ARGV[i]; printf $NF" "};exit}' /some/dir/prefix*

【讨论】:

    【解决方案4】:

    使用 awk 的一种方法:

    ls /some/dir/prefix* | awk -F"." '{printf "%s ", $2} END {print ""}'
    

    它可能有资格被称为“更好”,因为只有一个命令输出通过管道传输?!

    【讨论】:

    • @Iubgr,老实说,我们不应该将ls 的输出传递给外部程序。
    • 减少管道命令的数量正是我想要的。我更喜欢 Benjamins 的回答,因为它具有更好的可读性(IMO)
    猜你喜欢
    • 2021-06-17
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多