Awk

從儲存為文件名的日期設置文件修改日期

  • September 25, 2021

我有很多文件,其中文件名包含文件創建日期(IMG_YYYYMMDD_hhmmss.jpg):

IMG_20171015_133516.jpg
IMG_20171015_133827.jpg
IMG_20171015_142634.jpg
IMG_20171015_142834.jpg
IMG_20171015_142857.jpg

但實際文件創建日期不同。我需要從文件名將其設置回日期。

我知道如何將所有文件的日期更改為目前日期:

find -type f -exec touch {} \;

以及如何解析文件名以獲取正確格式的日期touch -t

echo IMG_20171015_133516.jpg | awk -F_ '{print $2 substr($3,0,4) "." substr($3,5,2)}'
201710151335.16

但我不知道如何將這些命令組合在一起來更改所有文件。

find -type f -exec touch -t"$(echo '{}' | awk -F_ '{print $2 substr($3,0,4) "." substr($3,5,2)}')" {} \;

返回

觸摸:無效的日期格式“。”

在外殼中:

for f in ./IMG_*.jpg ; do 
   t=${f##*/} 
   touch "$f" -t "${t:4:8}${t:13:4}.${t:17:2}"
done

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 {} \+

腳本後 Bash 的第一個參數轉到$0變數,該變數通常包含 shell 名稱。其餘的轉到位置參數$1,$2等和for forfor 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)

引用自:https://unix.stackexchange.com/questions/409564