ファイル名を読み、ファイルを別のディレクトリに移動します。

ファイル名を読み、ファイルを別のディレクトリに移動します。

ファイル名を読んでファイルを移動する必要があります。システム生成ファイルを移動する必要がありますが、名前にタイムスタンプが含まれています。毎月ファイル名を読んでファイルを移動する必要があります。

ファイル名にが含まれている場合は、ディレクトリ201601*.txtに移動します2016/January。ファイル名に以下が含まれている場合は、ディレクトリなど201602*.txtに移動します。2016/February

答え1

日付文字列がファイル名にあり、すべてのファイルが同じディレクトリにある場合は、次のことができます。

mv 201601*.txt 2016/January

この操作を手動で12回実行するのは面倒なことがあるので、数字とその月の名前を含むリストを作成します。

$ paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') 
01  January
02  February
03  March
04  April
05  May
06  June
07  July
08  August
09  September
10  October
11  November
12  December

その後、それを解析してmvコマンドをビルドします。

$ paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') | 
    while read num month; do echo mv "*2016$num*" 2016/"$month"; done
mv *201601* 2016/January
mv *201602* 2016/February
mv *201603* 2016/March
mv *201604* 2016/April
mv *201605* 2016/May
mv *201606* 2016/June
mv *201607* 2016/July
mv *201608* 2016/August
mv *201609* 2016/September
mv *201610* 2016/October
mv *201611* 2016/November
mv *201612* 2016/December

要件が満たされている場合は、削除してecho実際にファイルを移動してください。

paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') | 
    while read num month; do echo mv "*2016$num*" 2016/"$month"; done

説明する

Perl準拠の正規表現()を使用して実行し、各行grep -Po '\s+\K[A-Z]\w{2,}')の一致部分のみを印刷します()。使用される正規表現は、1つ以上の空白文字()、その後に大文字()、および2つ以上の単語文字()を検索します。 「この前の内容はすべて無視します」という意味で、コマンドが一致する文字列部分のみを印刷するようにします。grep-P-o\s+[A-Z]\w{2,}\K後ろにスペース。全体のプロセスでは、月のリストのみを印刷します。

答え2

ジッシュ名前パターンに基づいてファイル名を変更する良い機能があります。zmv。代替モードでは、$f元の名前全体が指定されます$1$2などは括弧内のグループです。月名を保存するには配列を使用してください。

autoload -U zmv
months=(January February March April May June July August September October November December)
zmv '(2016)(<1-12>)*.txt' '$1/$months[$2]/$f'

ここのパターンは単純なので、ループを使用してbashとkshに適用することはそれほど難しくありません。いくつかの点に注意する必要があります。月番号から前のゼロを削除すると、配列インデックスがゼロから始まると解釈されません。

months=(January February March April May June July August September October November December)
for f in 2016[0-9][0-9]*; do
  y=${f:0:4} m=${f:4:2}
  mv -- "$f" "$y/${months[${m#0}]}/$f"
done

別のアプローチはPerlの名前変更スクリプト(またはDebian バージョンまたはUnicode::バトルバージョン)。

rename 'BEGIN {@months = qw(January February March April May June July August September October November December)}
        s!^([0-9]{4})([0-9]{2})!$1/$months[$2]/&!' 2016[0-9][0-9]*

答え3

以下は、bashファイルを繰り返してコンポーネントに一致するファイルを移動するソリューションです(yyyymm2000〜2099の範囲の値について)。yyyy

months=('' January February March April May June July August September October November December)

for f in 20[0-9][0-9][0-3][0-9]*
do
    year=$(echo "$f" | grep -Po '^20\d\d')           # Extract the four digit year, 20nn
    mm=$(echo "$f" | grep -Po '^(?<=20\d\d)\d\d')    # Find the two digit month number 01-12
    month=${months[$mm]}                             # Convert to a month name

    test -n "$year" -a -n "$month" && echo mv "$f" "$yyyy/$month/$f"
done

実行する準備ができたら、echoプレフィックスを削除してください。mv


すべてのファイルが次から始まることがわかっている場合、2016これは少し簡単になります。

for f in 2016[0-3][0-9]*
do
    mm=$(echo "$f" | grep -Po '^(?<=2016)\d\d')    # Find the two digit month number 01-12
    month=${months[$mm]}                           # Convert to a month name

    test -n "$month" && echo mv "$f" "2016/$month/$f"
done

関連情報