You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从文件名中的日期字符串设置文件修改时间

问题分析与解决方案

你遇到的核心问题确实是命令替换的执行时机不对——当你写$(sed -e ... {})的时候,这个命令替换是由调用xargs的父shell先执行的,而不是xargs每次处理一个文件时才执行。这时候{}还只是一个占位符字符串,sed处理的是字面量{},而不是实际的文件名,所以生成的"日期"完全不符合要求,touch自然会报错。

下面给你几个可行的命令行解决方案,不用写单独的脚本就能解决:

方案1:用xargs + bash子shell处理每个文件

把sed的处理逻辑放到bash子shell里,让每个文件名都能被单独解析:

find . -name "*.xz" | xargs -I {} bash -c '
  DATE=$(sed -e "s/\.tar\.xz//g; s/user-//g; s/\.//g; s/\///g; s/$/0000/g" <<< "$1")
  touch -m -t "$DATE" "$1"
' _ {}
  • 这里bash -c启动一个子shell,$1代表传入的文件名(也就是{})
  • <<< "$1"把文件名作为输入传给sed,确保每个文件都能被正确处理
  • _是bash -c脚本的第一个参数(对应$0,我们用不到,所以填个占位符)

方案2:用awk简化日期提取(更简洁)

比起多次sed替换,用awk直接分割文件名提取日期部分更高效:

find . -name "*.xz" | xargs -I {} bash -c '
  DATE=$(echo "$1" | awk -F "[-.]" "{print \$2\$3\$4\"0000\"}")
  touch -m -t "$DATE" "$1"
' _ {}
  • -F "[-.]"用-和.作为分隔符,文件名./user-2018.12.20.tar.xz会被分成./user、2018、12、20、tar、xz这几部分
  • 直接拼接$2$3$4得到20181220,再加上0000就符合touch -t要求的格式了

方案3:用find的-exec替代xargs(更安全)

如果文件名里有空格或者特殊字符,xargs可能会出错,用find -exec更可靠:

find . -name "*.xz" -exec bash -c '
  DATE=$(sed -e "s/\.tar\.xz//g; s/user-//g; s/\.//g; s/\///g; s/$/0000/g" <<< "$1")
  touch -m -t "$DATE" "$1"
' _ {} \;

或者awk版本:

find . -name "*.xz" -exec bash -c '
  DATE=$(echo "$1" | awk -F "[-.]" "{print \$2\$3\$4\"0000\"}")
  touch -m -t "$DATE" "$1"
' _ {} \;

为什么原命令会失败?

再明确一下:原命令中$(sed ... {})是在xargs开始执行前就被父shell解析了。这时候{}还没被替换成实际的文件名,sed处理的是字符串{},输出的结果肯定不是你想要的日期格式,touch收到错误的日期参数,加上后面正确的文件名,就会抛出invalid date format的错误。

内容的提问来源于stack exchange,提问作者tobiasfried

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:23:20