【发布时间】:2018-06-18 23:53:47
【问题描述】:
我正在尝试编写一个简单的 bash 脚本来查看目录并删除与模式匹配的文件的所有版本(最新版本除外)。这个命令很好用:
find . -type f -name 'a.*.log' -printf '%T@\t%p\n' \
| sort -t $'\t' -g \
| head -n -2 \
| cut -d $'\t' -f 2- \
| xargs rm -f
这将获取以下文件:a.1.log、a.2.log 和 a.3.log,并删除 a.1.log(假设它是时间戳最旧的)。文件名的版本部分是一个哈希,所以不是按数字顺序排列的(为了简单起见,我更改了它)。
所以,我想做的是遍历一组不同的模式,并将每个模式提供给上面的 find 命令。我已将此示例的脚本简化为如下所示:
#!/bin/bash
FILES="a.*.log
b.*.log
c.*.log"
for f in $FILES
do
echo "Processing $f"
find . -type f -name "$f"
done
我运行它的目录有这些文件:
a.1.log, a.2.log, a.3.log, b.1.log, b.2.log, b.3.log, c.1.log, c.2.log , c.3.log
我从上面的脚本得到的输出是:
处理a.1.log ./a.1.log 处理a.2.log ./a.2.log 处理a.3.log ./a.3.log 处理 b.1.log ./b.1.log 处理 b.2.log ./b.2.log 处理 b.3.log ./b.3.log 处理 c.1.log ./c.1.log 处理 c.2.log ./c.2.log 处理 c.3.log ./c.3.log我需要的是输出看起来像这样:
处理 a.*.log ./a.1.log ./a.2.log ./a.3.log 处理 b.*.log ./b.1.log ./b.2.log ./b.3.log 处理 c.*.log ./c.1.log ./c.2.log ./c.3.log我尝试过使用数组而不是循环遍历字符串、转义文件模式、在查找中使用单引号和双引号等...但我无法简单地将模式替换为查找.如果我手动单独运行查找,它会给我我正在寻找的输出:
$查找。 -type f -name "a.*.log" ./a.1.log ./a.2.log ./a.3.log $查找。 -type f -name "b.*.log" ./b.1.log ./b.2.log ./b.3.log $查找。 -type f -name "c.*.log" ./c.1.log ./c.2.log ./c.3.log我找不到任何人循环遍历一组模式并将它们替换为命令的示例。任何帮助都会很棒。
谢谢。
【问题讨论】:
-
请注意,文件名包含文字换行符是非常合法的;因此,NUL 分隔的流比换行符更安全。
-
类似地,当
xargs没有通过-0或-d时,它会解析空格——如果你有c. foo bar.log,它会尝试删除文件c.,@ 987654328@,和bar.log。 -
顺便说一句——你回滚我的格式更改是故意的吗?将代码格式化为文本(一行,没有语法高亮或代码格式化)会严重影响其可读性。
-
顺便说一句,如果你想在没有代码格式的情况下显示数据,四个空格缩进是合适的——只需在块前面加上
<!-- language: none -->以禁用语法突出显示。 -
抱歉格式化。我已将所有 shell 输出作为代码放入,它是语法突出显示它不应该有的地方。我正在修复它。没想到反应这么快。
标签: regex bash loops find substitution