web-dev-qa-db-ja.com

ファイル名の末尾に日付変更タイムスタンプが付いた一連のファイルの名前を変更しますか?

たとえば、g.txtのような一連のファイルを含むディレクトリがあり、g.txtは2012年6月20日などに最後に変更されたとします。

2012年6月20日の最終更新日が最後に追加されたすべてのファイル(g.txtなど)の名前を一括変更するにはどうすればよいですか?

14
InquilineKea

現在のディレクトリにあるすべての(globed)ファイルの名前をfilename.txtからfilename.txt-20120620

for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done

進取的なBashのオタクはそれを打破するためにいくつかのエッジケースを見つけるでしょう、私は確信しています。 :)

明らかに、これは、ファイルの最後に日付のように見えるものが既にあるかどうかをチェックするような望ましいことをしません。

13
jgoldschrafe

これがgoldschrafeのワンライナーのバージョンです。

  • statを使用しない
  • 以前のバージョンのGNU日付で動作します
  • ファイル名のスペースに正しく対応
  • ダッシュで始まるファイル名にも対応

    for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done

19
cas

必須のzshワンライナー(オプションコンポーネントの1回限りのロードはカウントされません):

zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'

組み込みのstatzsh/stat module 、および zmv ファイル名を変更する関数。そして、もしあれば、これは拡張の前に日付を置くエキストラです。

zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'

私が理解したように、私たちは変更日付が何であるかを事前に知りません。したがって、各ファイルから取得し、出力をフォーマットし、ファイル名に変更日が含まれるように各ファイルの名前を変更する必要があります。

このスクリプトを「modif_date.sh」のようなものとして保存し、実行可能にすることができます。ターゲットディレクトリを引数として呼び出します。

modif_date.sh txt_collection

「txt_collection」は、名前を変更するすべてのファイルがあるディレクトリの名前です。

#!/bin/sh

# Override any locale setting to get known month names
export LC_ALL=c
# First we check for the argument
if [ -z "$1" ]; then
    echo "Usage: $0 directory"
    exit 1
fi

# Here we check if the argument is an absolute or relative path. It works both ways
case "${1}" in
  /*) work_dir=${1};;
  *) work_dir=${PWD}/${1};;
esac

# We need a for loop to treat file by file inside our target directory
for i in *; do
    # If the modification date is in the same year, "ls -l" shows us the timestamp.
    # So in this case we use our current year. 
    test_year=`ls -Ggl "${work_dir}/${i}" | awk '{ print $6 }'`
    case ${test_year} in *:*) 
        modif_year=`date '+%Y'`
        ;;
    *)
        modif_year=${test_year}
        ;;
    esac
    # The month output from "ls -l" is in short names. We convert it to numbers.
    name_month=`ls -Ggl "${work_dir}/${i}" | awk '{ print $4 }'`
    case ${name_month} in
            Jan) num_month=01 ;;
            Feb) num_month=02 ;;
        Mar) num_month=03 ;;
        Apr) num_month=04 ;;
        May) num_month=05 ;;
        Jun) num_month=06 ;;
        Jul) num_month=07 ;;
        Aug) num_month=08 ;;
        Sep) num_month=09 ;;
        Oct) num_month=10 ;;
        Nov) num_month=11 ;;
        Dec) num_month=12 ;;
        *) echo "ERROR!"; exit 1 ;;
    esac
    # Here is the date we will use for each file
    modif_date=`ls -Ggl "${work_dir}/${i}" | awk '{ print $5 }'`${num_month}${modif_year}
    # And finally, here we actually rename each file to include
    # the last modification date as part of the filename.
    mv "${work_dir}/${i}" "${work_dir}/${i}-${modif_date}"
done
1
Aline

これが idempotence で拡張された(goldschrafeのワンライナーに基づく)casのワンライナーのバージョンです。

つまり、ファイルに日付と時刻のプレフィックスを付けるように拡張され、日付と時刻のプレフィックスがまだない場合にのみこれを行うように拡張されています

使用例:新しいファイルをディレクトリに追加し、まだ日時のないファイルに日時の接頭辞を追加する場合に役立ちます。

for f in * ; do
  if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
    mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
  fi;
done