根据文件名中的日期字符串设置文件修改时间

时间:2019-04-19 07:58:39

标签: linux bash shell sed xargs

我正在还原一些名称中带有日期的档案,大致类似于:

user-2018.12.20.tar.xz
user-2019.01.10.tar.xz
user-2019.02.25.tar.xz
user-2019.04.19.tar.xz
...

我想通过touch将文件名传递到xargs并使用replace-str设置日期来设置每个文件的修改日期,使其与文件名中的日期匹配。

touch -m -t将采用[CCYYMMDDhhmm]格式的日期时间,但是在替换内联时遇到了麻烦:

find . -name "*.xz" | xargs -I {} touch -m -t $(sed -e 's/\.tar\.xz//g; s/user-//g; s/\.//g; s/\///g; s/$/0000/g' {}) {}

返回touch: invalid date format ‘./user-2018.03.22.tar.xz’,即使这样:

find . -name "*.xz" | sed -e 's/\.tar\.xz//g; s/user-//g; s/\.//g; s/\///g; s/$/0000/g'

返回格式正确的日期,例如201812200000。我是否会以某种方式在替换字符串中滥用命令替换?

编辑:是的,简单的脚本可以做到这一点。但是问题仍然存在...

3 个答案:

答案 0 :(得分:4)

您不需要findsedxargs或任何第三方工具,而只需使用Shell内置的正则表达式功能即可从文件中获取时间戳记

 for file in *.tar.xz; do
     [ -f "$file" ] || continue
     if [[ $file =~ ^user-([[:digit:]]+).([[:digit:]]+).([[:digit:]]+).tar.xz$ ]]; then
         dateStr="${BASH_REMATCH[1]}${BASH_REMATCH[2]}${BASH_REMATCH[3]}0000"
         touch -m -t "$dateStr"
     fi
 done

答案 1 :(得分:4)

问题在于,当您调用xargs时,命令替换将被评估一次,而不是针对每个参数。您需要为此生成一个shell:

find . -name "*.xz" \
  | xargs -I {} bash -c 'touch -m --date "$(sed -e "s/\.tar\.xz//;s/user-//g; s/\.//g; s/\///g;" <<< "$1")" "$1"' -- {}

注意:不需要xargs,因为您可以使用-exec的{​​{1}}选项:

find

PS:一个小的for循环将更具可读性:

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

答案 2 :(得分:3)

这可能对您有用(GNU并行):

parallel --dryrun touch -m --date '{= s/[^0-9]//g =}' {} ::: *.xz

对命令正确无误后,请删除--dryrun选项。

替代:

parallel touch -m --date `{= s/user-//;s/\.tar\.xz//;s/\.//g =}' {} ::: *.xz