【问题标题】:export filenames to temp file bash将文件名导出到临时文件 bash
【发布时间】:2015-04-20 19:07:50
【问题描述】:

我在多个目录中有很多文件,它们的文件名都具有以下设置:

prob123456_01

我想删除每个文件名后面的“_01”并将它们导出到临时文件。我将如何删除尾随的“_01”以及导出?我对脚本比较陌生,因此非常感谢任何帮助!

【问题讨论】:

  • 将它们导出到临时文件是什么意思?你的意思是每个文件名都应该打印到文件中吗?您能否更明确地说明每个文件名遵循的模式?
  • 你想如何表示临时文件中的文件名?请注意,UNIX 上的文件名可以包含文字换行符,因此尝试通过在文件名之间放置换行符来分隔文件名流很容易被控制这些名称的攻击者滥用。

标签: regex bash unix filenames


【解决方案1】:

正如您使用 标记的那样,我假设您可以使用globstar

shopt -s globstar # enable globstar
for f in **_[0-9][0-9]; do echo "${f%_*}"; done > tmp

启用globstar 后,模式**_[0-9][0-9] 匹配当前目录和任何子目录中以_ 结尾的任何文件,后跟任何2 位数字。 ${f%_*} 使用 bash 的内置字符串操作功能删除文件名的结尾。

更好的是,正如Charles Duffy 建议的(谢谢),您可以使用数组而不是循环:

files=( **_[0-9][0-9] ); printf '%s\n' "${files[@]%_*}"

数组中填充了与以前相同的模式匹配的文件名。 ${files[@]%_*} 从数组的每个元素中删除最后一部分并将它们作为参数传递给printfprintf 将每个结果打印在单独的行上。

这两种方法中的任何一种都可能比使用find 更快,因为一切都在 shell 中完成,无需执行任何单独的进程。

之前我曾建议使用**_{00..99} 模式,尽管出于几个原因这并不理想。它的效率较低,因为它扩展到**_00**_01**_02...**_99。此外,除非启用了另一个选项 nullglob,否则这 100 个不匹配的模式中的任何一个都将直接包含在输出中。

使用[0-9][[:digit:]] 取决于您,但后者的优点是它匹配定义为数字的所有字符,这可能因您的语言环境而异。如果这不是问题,我会选择前者。

【讨论】:

    【解决方案2】:

    如果我对您的理解正确,您需要一个不带尾随 _01 的文件名列表。以下将做到这一点:

    find . -type f -name '*_01' | sed 's/_01$//' > tmp.lst
    

    find . -type f -name '*_01' 查找当前目录及其后代目录中的所有文件,以查找名称以_01 结尾的文件。

    |就是所谓的管道,把左手调用的结果交给右手调用。

    sed 's/_01$//' 删除每个文件名末尾的_01

    > tmp.lst将结果写入文件tmp.lst

    这些都是使用bash 及其类似工具的非常基本的部分,因此查看一两个教程并熟悉这些和其他一些内容可能是个好主意;)

    【讨论】:

    • 谢谢!我一直在努力熟悉自己,但我有点难过。另外,我将如何修改 find 语句以查找任何具有“_”后跟任何两个整数的文件? (不仅仅是01)
    • @你能不能把模式改成'*_[0-9][0-9]'
    猜你喜欢
    • 1970-01-01
    • 2013-11-05
    • 2016-07-27
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 2014-02-07
    • 2012-05-21
    相关资源
    最近更新 更多