Como organizar arquivos em lote?

3

Eu tenho um diretório com gigabytes (cerca de 8GB) de pequenos arquivos individuais. Eu quero organizá-los em diretórios por data. A data em que foi criada faz parte do nome do arquivo.

Aqui está um exemplo de um nome de arquivo:

4RCPBlockCoverLtrednalaserfalse07-10-2012-11-50-14-656.doc.gz

Eu quero a configuração do diretório docs assim:

docs_by_date
    2013
        01
        02
        03
        04

Se o diretório de destino não existir, ele deve ser criado. Após a verificação de uma cópia bem sucedida, o arquivo de origem deve ser removido.

Eu não sou super guru com bash, muitos dos símbolos eu ainda não sei o que eles significam, então uma explicação seria ótima do que o script está fazendo.

    
por Mike De 13.08.2013 / 23:20

2 respostas

3

Suponho que, para o arquivo 07-10-2012-11-50-14-656.doc.gz , você deseja classificá-lo por ano (ou seja, 2012 ) e mês (ou seja, 10 ).

#!/usr/bin/env bash
# This is the preferred way of invoking a bash script, and is better than #!/bin/bash for reasons of portability.
# To use the script, make it executable with 'chmod u+x /path/to/script'
# Then run this script with '/path/to/script /path/to/original/files /path/to/docs_by_date'

# Let's set up some path variables. This script will transfer files from the directory specified by the first argument to the directory specified by the second.
pathtooriginalfiles=
pathtotarget=

# Lets iterate over the files in the original directory, by listing all non-invisible files with $(ls ${pathtooriginalfiles}), and repeating the block with $i changing each time.
for i in $(ls "${pathtooriginalfiles}"); do
  # Find the matching parts of the filename that specify the date by echoing then piping the variable to sed. The regex part looks for "everything at the beginning" ^.*, followed by two iterations of digits [0-9]{2}, followed by four iterations of digits, etc. before ending with .doc.gz. It then replaces this entire string with what matches between () using the  variable, i.e. the year or month.
  year=$(echo -n ${i}| sed -r 's/^.*[0-9]{2}-([0-9]{4})-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{3}\.doc\.gz$//')
  month=$(echo -n ${i}| sed -r 's/^.*([0-9]{2})-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{3}\.doc\.gz$//')

  # Create the directory if it doesn't exist already, then copy into it.
  mkdir -p "${pathtotarget}/${year}/${month}"
  cp "${pathtooriginalfiles}/${i}" "${pathtotarget}/${year}/${month}"
done

Além disso, não codifiquei exatamente o que você solicitou. Você disse que deve testar para ver se os arquivos estão lá e depois excluí-los automaticamente. Em vez disso, esse script apenas os copia e deixa os originais em paz. Eu recomendo que você "teste" manualmente para ter certeza de que faz o que você acha que deveria, em vez de confiar no script para fazer isso sozinho. (Qualquer erro na parte de cópia provavelmente seria replicado na parte de verificação.) Se você realmente quiser que o script remova os originais, basta alterar a cp part para mv . (Sinto que o mv é mais limpo do que copiar e excluir de qualquer maneira. Um dos motivos é que cp não faz checksum, embora você possa usar rsync -a .

    
por Sparhawk 14.08.2013 / 06:24
0

Ok, parece que descobri, devido à sua ajuda!

Foi um erro simples! Existem 7 campos, em vez de 6! Se você olhar o nome do arquivo original:

4RCPBlockCoverLtrednalaserfalse 07 -10- 2012 -11-50-14-656.doc.gz

  • a seção em negrito é o que estamos procurando. Ano (2012) e Mês (7). No roteiro estava tratando 10 (entre os 07 e os 2012) como o primeiro campo! Tudo o que fiz foi adicionar o [0-9] {2} entre eles e pronto, funciona!

Este é o script que você me deu e então você pode ver como eu o editei.

Obrigado pela sua ajuda muuuito mais! Salvei meu dia!

#!/usr/bin/env bash
pathtooriginalfiles=
pathtotarget=

for i in $(ls "${pathtooriginalfiles}"); do

year=$(echo -n ${i}| sed -r 's/^.*[0-9]{2}-[0-9]{2}-([0-9]{4})-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{1,3}\.doc\.gz$//')
month=$(echo -n ${i}| sed -r 's/^.*([0-9]{2})-[0-9]{2}-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{1,3}\.doc\.gz$//')

echo $year $month
  mkdir -p "${pathtotarget}/${year}/${month}"
   ls -l $pathtotarget
  cp -auv "${pathtooriginalfiles}/${i}" "${pathtotarget}/${year}/${month}/"
done

o "," entre {1,3} foi fundamental para mim pessoalmente.

e o "/" no final da string do cp $ {month} / "foi a chave também.

    
por Mike De 17.08.2013 / 09:56