mx0*_*mx0 1 find awk date files touch
我有很多文件,其中文件名包含文件创建日期 ( IMG_RRRRMMDD_hhmmss.jpg
):
IMG_20171015_133516.jpg
IMG_20171015_133827.jpg
IMG_20171015_142634.jpg
IMG_20171015_142834.jpg
IMG_20171015_142857.jpg
Run Code Online (Sandbox Code Playgroud)
但实际文件创建日期不同。我需要将它从文件名设置回日期。
我知道如何将所有文件的日期更改为当前日期:
find -type f -exec touch {} \;
Run Code Online (Sandbox Code Playgroud)
以及如何解析文件名以获取正确格式的日期 touch -t
echo IMG_20171015_133516.jpg | awk -F_ '{print $2 substr($3,0,4) "." substr($3,5,2)}'
201710151335.16
Run Code Online (Sandbox Code Playgroud)
但我不知道如何将这些命令组合在一起来更改所有文件。
find -type f -exec touch -t"$(echo '{}' | awk -F_ '{print $2 substr($3,0,4) "." substr($3,5,2)}')" {} \;
Run Code Online (Sandbox Code Playgroud)
返回
触摸:无效的日期格式“.”
在外壳中:
for f in ./IMG_*.jpg ; do
t=${f##*/}
touch "$f" -t "${t:4:8}${t:13:4}.${t:17:2}"
done
Run Code Online (Sandbox Code Playgroud)
Bash、ksh、zsh 等都有${var:n:m}
子字符串扩展,如果需要递归扩展,请启用globstar
并使用**/IMG_*.jpg
。
这样做也find
需要外壳:
$ find -name "IMG_*.jpg" -exec bash -c '
for f; do t=${f##*/}; touch "$f" -t "${t:4:8}${t:13:4}.${t:17:2}" ; done
' sh {} \+
Run Code Online (Sandbox Code Playgroud)
脚本后 Bash 的第一个参数转到$0
变量,该变量通常包含 shell 名称。其余转到位置参数$1
,$2
等,for f
或for f in "$@"
循环他们。这里的构造相当常见(至少在 unix.SE 答案中)。此处循环的主要部分与第一个示例中的相同。
在find
你的问题中的命令find .. -exec touch -t"$(...)" {} \;
不起作用,因为该命令替换为双引号,所以它得到扩大之前find
运行。该{}
是字面上的管道awk
,它只是恰巧,该awk
脚本只打印一个点。
如果您确实将命令替换放在单引号中,它将按touch
原样传递给(find
只会替换{}
)。touch
会得到参数-t$(echo ...)
,美元符号,括号等等。find
不会自己通过 shell 运行命令,我们需要明确地执行它,如上所述。
在单引号示例中:
$ find -name x -exec echo 'hello $(foo {})' \;
hello $(foo ./x)
Run Code Online (Sandbox Code Playgroud)