ファイル名で保存された日付に基づいてファイル変更日を設定します。

ファイル名で保存された日付に基づいてファイル変更日を設定します。

ファイル名にファイル作成日()を含むファイルがたくさんあります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)}')" {} \;

返品

タッチ: 間違った日付形式 "."

答え1

シェルから:

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シェル名を含む変数を指します。残りは位置引数などに移動する$1か、$2それを繰り返しますfor ffor f in "$@"ここの設定はかなり一般的です(少なくともunix.SEの答えでは)。このループの主要部分は、最初の例と同じです。


find質問のコマンドは、find .. -exec touch -t"$(...)" {} \;コマンド置換が二重引用符で囲まれて機能しないため、find実行する前に拡張されます。文字通り{}にパイプされ、スクリプトはドットのみを印刷しますawkawk

コマンドの置き換え一つ引用符を使用すると、touchそのまま渡されます(find置換のみ可能{})。パラメータ、ドル記号、括弧などがtouch表示されます。シェル自体を介してコマンドを実行するのではなく、上記のように明示的に実行する必要があります。-t$(echo ...)find

一重引用符を例にしてみましょう。

$ find -name x -exec echo 'hello $(foo {})' \;
hello $(foo ./x)

関連情報