Estranha formatação de data no script bash

3

Estou trabalhando em um script para classificar minha pasta de downloads pela data em que os arquivos foram criados. Este é o script que estou usando:

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

O nome da pasta criada por este script é apenas Jun , o que me leva a acreditar que há algum tipo de conversão acontecendo em algum lugar.

Se eu fizer apenas um

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

a data mostra 19062014 corretamente.

Este é o resultado de um bash -x do script:

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

A funcionalidade que estou procurando é que o script mova os arquivos para pastas denominadas 19_06_2014 , 20_06_2014 etc. com base em quando o arquivo foi criado.

    
por slopedoo 19.06.2014 / 20:59

3 respostas

3

Palpite: você tem um alias para ls que está sendo usado quando você tenta o comando interativamente, e esse alias não é usado no script. Algo assim, talvez?

alias ls="ls --full-time"

Note que a sabedoria convencional diz que tentar analisar ls é uma má ideia. Supondo que você esteja em uma máquina Linux, algo assim pode ser preferível:

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

EDIT: Ou, como Stéphane aponta abaixo, usar find com -printf é ainda melhor. A saída de stat é um pouco mais fácil de prever do que ls , mas -printf permite um formato de saída totalmente controlado por você.

    
por 19.06.2014 / 21:33
7

Sugiro usar um formato de data como 2014-06-19 . Dessa forma, um ls os mostraria em ordem cronológica.

Em um sistema GNU:

#! /bin/bash -
cd ~/Downloads &&
  find . -maxdepth 1 -type f -printf '%p
#! /bin/zsh
zmodload zsh/stat || exit

cd ~/Downloads &&
  for file (./*(ND.)) {
    zstat -A date -F %F +mtime $file &&
      mkdir -p $date &&
      mv $file $date
  }
%TF
#! /bin/bash -
cd ~/Downloads &&
  find . -maxdepth 1 -type f -printf '%p
#! /bin/zsh
zmodload zsh/stat || exit

cd ~/Downloads &&
  for file (./*(ND.)) {
    zstat -A date -F %F +mtime $file &&
      mkdir -p $date &&
      mv $file $date
  }
%TF%pre%' | while IFS= read -rd '' file && read -d '' date; do mkdir -vp "$date" && mv "$file" "$date" done
' | while IFS= read -rd '' file && read -d '' date; do mkdir -vp "$date" && mv "$file" "$date" done

Com zsh em qualquer sistema:

%pre%     
por 19.06.2014 / 22:02
0

Aqui está o código completo

#!/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 -
    
por 19.06.2014 / 21:48