ファイル名にファイル作成日()を含むファイルがたくさんあります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 f
。for f in "$@"
ここの設定はかなり一般的です(少なくともunix.SEの答えでは)。このループの主要部分は、最初の例と同じです。
find
質問のコマンドは、find .. -exec touch -t"$(...)" {} \;
コマンド置換が二重引用符で囲まれて機能しないため、find
実行する前に拡張されます。文字通り{}
にパイプされ、スクリプトはドットのみを印刷しますawk
。awk
コマンドの置き換え一つ引用符を使用すると、touch
そのまま渡されます(find
置換のみ可能{}
)。パラメータ、ドル記号、括弧などがtouch
表示されます。シェル自体を介してコマンドを実行するのではなく、上記のように明示的に実行する必要があります。-t$(echo ...)
find
一重引用符を例にしてみましょう。
$ find -name x -exec echo 'hello $(foo {})' \;
hello $(foo ./x)