Странное форматирование даты в скрипте bash

Странное форматирование даты в скрипте 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_2014и 20_06_2014т. д. в зависимости от того, когда был создан файл.

решение1

Я бы предложил использовать формат даты, например 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
  }

решение2

Дикая догадка: у вас есть псевдоним для lsэтого, который используется, когда вы пытаетесь выполнить команду интерактивно, и этот псевдоним не используется в скрипте. Что-то вроде этого, возможно?

alias ls="ls --full-time"

Обратите внимание, что общепринятая мудрость гласит, что попытка парсинга ls— плохая идея. Если вы работаете на Linux-машине, то предпочтительнее будет сделать что-то вроде этого:

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

EDIT: Или, как указывает Стефан ниже, использование findwith -printfдаже лучше. Вывод statнемного легче предсказать, чем ls, но -printfпозволяет использовать формат вывода, который полностью контролируется вами.

решение3

Вот полный код

#!/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 -

Связанный контент