在 bash for 循环中使用命令替换

在 bash for 循环中使用命令替换

我可能犯了一个明显的错误,但我可以使用一个强烈的提示:-)

for file in *; do ls $file | var=$(ls $file | grep -Eo '.{18}$' | cut -d '.' -f1 |sed 's/.\{12\}/&./'); echo "var is $var. File is $file";done

结果: $var 为空。 $file 不是。为什么 $var 为空?

当我手动将测试字符串放入 $file 并按如下方式运行时,$var 包含我想要的内容:

var=$(ls $file | grep -Eo '.{18}$' | cut -d '.' -f1 |sed 's/.\{12\}/&./')

所以有一些关于 for 循环的事情导致了这种情况。看来 $var 变量有范围限制,阻止我在以下语句中使用。

祝你复活节愉快:-)

完整示例:

正如所问,这是一个示例,希望能够澄清我的疑问。文件的inventory_a_test-20190605161153.txt1日期必须与其文件名中的日期匹配。首先,我将文件设置为错误的日期:

$ touch inventory_a_test-20190605161153.txt
$ ls -l --full-time inventory_a_test-20190605161153.txt
-rw-rw-r-- 1 root root 0 **2021-04-05** 15:02:05.000000000 +0200 inventory_a_test-20190605161153.txt

现在我想在 bash 中编写一个如下所示的命令流作为 for 循环来更正日期:

$ file=inventory_a_test-20190605161153.txt
$ ls $file | grep -Eo '.{18}$' | cut -d '.' -f1 |sed 's/.\{12\}/&./'
201906051611.53
$ touch -a -m -t 201906051611.53 $file
$ ls -l --full-time inventory_a_test-20190605161153.txt
-rw-rw-r-- 1 root root 0 **2019-06-05** 16:11:53.000000000 +0200   inventory_a_test-20190605161153.txt

答案1

这部分没有意义:

ls $file | $(something)

$(command)格式的意思是“运行command并将其输出视为变量”。这不是可以接受管道输入的东西。我想你什么意思是写的是:

for file in *; do 
    var=$(ls "$file" | grep -Eo '.{18}$' | cut -d '.' -f1 |sed 's/.\{12\}/&./'); 
    echo "var is $var. File is $file"
done

然而,对于奇怪的文件名来说,这会严重失败。你真的不想解析输出ls。更重要的是,ls这里绝对不需要!你已文件名,因此ls只会增加复杂性和可能的​​错误源。这应该做你想要的:

for file in *; do
    timestamp=$(sed -E 's/.*(.{12})(..)\.[^.]*$/\1.\2/' <<<"$file")
    touch -a -m -t "$timestamp" -- "$file"
done

sed仅打印文件最终扩展名之前的最后 14 个字符(\.[^.]*$/将匹配 a .,然后匹配 0 或更多非 -.直到文件名末尾),但将最后 2 个字符与前 12 个字符分开,并.有效生成你的时间戳。

答案2

@terdon 不,谢谢你的好意解决方案。对于其他 Linux 初学者。我也遇到了一些时区问题,所以最终结果是:

for file in *; do
     timestamp=$(sed -E 's/.*(.{12})(..)\.[^.]*$/\1.\2/') <<<"$file"
     TZ=UTC-2 touch -a -m -t "$timestamp" -- "$file"
done

ps:我使用这个网站来分析正则表达式:https://regex101.com/

相关内容