web-dev-qa-db-ja.com

bashスクリプトでの日付の奇妙なフォーマット

ファイルが作成された日付でダウンロードフォルダーを並べ替えるスクリプトに取り組んでいます。これは私が使用しているスクリプトです:

#!/bin/bash

cd ~/Downloads
for FILENAME in *
do
    if [[ -f $FILENAME ]]; then
        date="$(ls -l $FILENAME | tr -s ' ' | cut -d ' ' -f 6 | tr -d '.')"
        mkdir -vp "$date"
        find . -maxdepth 1 -type f -name $FILENAME -exec mv {} "$date" \;
    fi
done
cd -

このスクリプトによって作成されたフォルダーの名前はJunであり、どこかで何らかの変換が行われていると私は信じています。

私がただするなら

ls -l test0 | tr -s ' ' | cut -d ' ' -f 6 | tr -d '.'

日付は19062014を正しく示しています。

これは、スクリプトのbash -xの結果です。

sigurd@Goliath ~ -> bash -x clean
+ cd /home/sigurd/Downloads
+ for FILENAME in '*'
+ [[ -f test0 ]]
++ ls -l test0
++ tr -s ' '
++ cut -d ' ' -f 6
++ tr -d .
+ date=Jun
+ mkdir -vp Jun
mkdir: created directory 'Jun'
+ find . -maxdepth 1 -type f -name test0 -exec mv '{}' Jun ';'
+ for FILENAME in '*'
+ [[ -f test1 ]]
++ ls -l test1
++ tr -s ' '
++ cut -d ' ' -f 6
++ tr -d .
+ date=Jun
+ mkdir -vp Jun
+ find . -maxdepth 1 -type f -name test1 -exec mv '{}' Jun ';'
+ cd -
/home/sigurd

私が探している機能は、スクリプトがファイルの作成時期に基づいて、ファイルを19_06_201420_06_2014などの名前のフォルダーに移動することです。

3
slopedoo

野蛮な推測:コマンドをインタラクティブに試すときに使用されているlsのエイリアスがあり、そのエイリアスはスクリプトでは使用されていません。たぶん、このようなもの?

alias ls="ls --full-time"

世間一般の通念では、lsを解析しようとするのは悪い考えだと言われていることに注意してください。 Linuxマシンを使用しているとすると、次のようなものが望ましい場合があります。

stat "$FILENAME" | awk '/^Modify: /{print $2}'

編集:または、Stéphaneが以下で指摘しているように、find-printfはさらに優れています。 statの出力は、lsよりも予測が少し簡単ですが、-printfは、完全にあなたが制御する出力フォーマットを可能にします。

3
godlygeek

2014-06-19のような日付形式を使用することをお勧めします。そうすれば、lsはそれらを時系列で表示します。

GNUシステムの場合:

#! /bin/bash -
cd ~/Downloads &&
  find . -maxdepth 1 -type f -printf '%p\0%TF\0' |
    while IFS= read -rd '' file && read -d '' date; do
      mkdir -vp "$date" && mv "$file" "$date"
    done

任意のシステムでzshを使用する場合:

#! /bin/zsh
zmodload zsh/stat || exit

cd ~/Downloads &&
  for file (./*(ND.)) {
    zstat -A date -F %F +mtime $file &&
      mkdir -p $date &&
      mv $file $date
  }
7

これが完全なコードです

#!/bin/bash
cd ~/Downloads
for FILENAME in $(find . -maxdepth 1 -type f); do    
    DATE=$(stat "$FILENAME" | awk '/^Modify: /{print $2}')
    [ ! -d "$DATE" ] && mkdir -vp "$DATE"

    mv "$FILENAME" "${DATE}/$FILENAME"
done
cd -
0
polym