从文件名中存在的日期字符串设置文件修改时间
Set file modification time from the date string present in the filename
我正在恢复一些名称中包含日期的档案,大致如下:
user-2018.12.20.tar.xz
user-2019.01.10.tar.xz
user-2019.02.25.tar.xz
user-2019.04.19.tar.xz
...
我想通过 xargs
将文件名传送到 touch
并使用 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' {}) {}
Returnstouch: 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'
Returns 格式正确的日期,例如 201812200000
。我是否以某种方式在我的替换字符串中滥用了命令替换?
编辑: 是的,一个简单的脚本就可以做到这一点。但问题仍然存在...
您不需要 find
、sed
、xargs
或任何第三方工具,只需使用 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
问题是当您调用 xargs
时命令替换将被评估一次,而不是对每个参数。您需要为此生成一个 shell:
find . -name "*.xz" \
| xargs -I {} bash -c 'touch -m --date "$(sed -e "s/\.tar\.xz//;s/user-//g; s/\.//g; s/\///g;" <<< "")" ""' -- {}
注意:不需要xargs
,因为您可以使用find
的-exec
选项:
find . -name "*.xz" -exec bash -c 'touch -m --date "$(sed -e "s/\.tar\.xz//;s/user-//g; s/\.//g; s/\///g;" <<< "")" ""' -- {} \;
PS: 一个小的 for 循环会更具可读性:
for file in user-*.tar.xz ; do
# remove prefix and suffix
date=${file#user-}
date=${date%.tar.xz}
# replace dots by /
date=${date//./\/}
touch -m --date "${date}" "${file}"
done
这可能对你有用(GNU 并行):
parallel --dryrun touch -m --date '{= s/[^0-9]//g =}' {} ::: *.xz
如果命令正确,则删除 --dryrun
选项。
选择:
parallel touch -m --date `{= s/user-//;s/\.tar\.xz//;s/\.//g =}' {} ::: *.xz
我正在恢复一些名称中包含日期的档案,大致如下:
user-2018.12.20.tar.xz
user-2019.01.10.tar.xz
user-2019.02.25.tar.xz
user-2019.04.19.tar.xz
...
我想通过 xargs
将文件名传送到 touch
并使用 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' {}) {}
Returnstouch: 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'
Returns 格式正确的日期,例如 201812200000
。我是否以某种方式在我的替换字符串中滥用了命令替换?
编辑: 是的,一个简单的脚本就可以做到这一点。但问题仍然存在...
您不需要 find
、sed
、xargs
或任何第三方工具,只需使用 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
问题是当您调用 xargs
时命令替换将被评估一次,而不是对每个参数。您需要为此生成一个 shell:
find . -name "*.xz" \
| xargs -I {} bash -c 'touch -m --date "$(sed -e "s/\.tar\.xz//;s/user-//g; s/\.//g; s/\///g;" <<< "")" ""' -- {}
注意:不需要xargs
,因为您可以使用find
的-exec
选项:
find . -name "*.xz" -exec bash -c 'touch -m --date "$(sed -e "s/\.tar\.xz//;s/user-//g; s/\.//g; s/\///g;" <<< "")" ""' -- {} \;
PS: 一个小的 for 循环会更具可读性:
for file in user-*.tar.xz ; do
# remove prefix and suffix
date=${file#user-}
date=${date%.tar.xz}
# replace dots by /
date=${date//./\/}
touch -m --date "${date}" "${file}"
done
这可能对你有用(GNU 并行):
parallel --dryrun touch -m --date '{= s/[^0-9]//g =}' {} ::: *.xz
如果命令正确,则删除 --dryrun
选项。
选择:
parallel touch -m --date `{= s/user-//;s/\.tar\.xz//;s/\.//g =}' {} ::: *.xz