Script para percorrer pastas com nomes numéricos

5

Estou trabalhando em um script bash para compactar as imagens em minhas pastas do Wordpress. A estrutura da pasta do wordpress é a seguinte:

> wp-content/uploads/2014/01/filename.jpg
> wp-content/uploads/2014/02/filename.jpg
> wp-content/uploads/2014/03/filename.jpg
> wp-content/uploads/2014/04/filename.jpg
> 
> i.e. wp-content/uploads/YEAR/MONTH/filename.jpg

Na pasta de uploads eu tenho um número de outras pastas (que foram criadas quando plugins foram instalados), então estou tentando percorrer as pastas apenas com nomes numéricos e depois compactar as imagens. Aqui está o que eu tenho até agora:

DIR_UPLOADS=/home/html/wp-content/uploads/
cd ${DIR_UPLOADS}    
for d in *; do                 # First level i.e. 2014, 2013 folders.
     regx='^[0-9]+$'           # Regular Expression to check for numerics.
     if [[$d =~ $regx]]; then  # Check if folder name is numeric.
       #echo "error: Not a number" >&2; exit 1
       cd $d
       for z in *; do          # Second level i.e. the months folders 01, 02 etc.
        cd $z
        for x in *; do         # Third level the actual file.              
          echo 'Compress Image'
        done
      done
     fi
    done

Estou tentando usar reg ex para detectar as pastas numéricas, isso não está certo, mas acho que estou perto.

    
por Stephen 14.04.2014 / 11:33

2 respostas

5

Você pode usar bash extended globbing para isso:

shopt -s extglob
DIR_UPLOADS=/home/html/wp-content/uploads/
cd ${DIR_UPLOADS}

for dir in $PWD/+([0-9])/+([0-9]); do
  cd "$dir" &&
    for file in *; do
      echo 'Compress Image'
    done
done

Da página do manual:

+(pattern-list)
    Matches one or more occurrences of the given patterns

Portanto, colocar um intervalo de números dentro corresponderá aos arquivos / diretórios. Adicionar a condicional && garantirá que você só comprima imagens se a correspondência for um diretório (e que você realmente tenha conseguido digitá-las).

Sem a globbing estendida, você poderia até mesmo fazer [1-2][0-9][0-9][0-9]/[0-1][0-9] . Isso é melhor do que tentar uma expansão de chave, já que você não tentará entrar nos diretórios para cada ano / mês, mesmo que você não tenha imagens a partir de então.

    
por 14.04.2014 / 11:46
2

Eu acho que teria feito isso usando find , mas apenas para ajudar a responder suas perguntas sobre scripts, eu modifiquei ligeiramente o seu exemplo.

#!/bin/bash

for d in *; do                # First level i.e. 2014, 2013 folders.
  regx='^[0-9]+$'             # Regular Expression to check for numerics.
  echo "dir: $d"
  if [[ $d =~ $regx ]]; then  # Check if folder name is numeric.
    echo "found num: $d"
    pushd $d >& /dev/null
    for z in *; do            # Second level i.e. the months folders 01, 02 etc.
      pushd $z >& /dev/null
      for x in *; do          # Third level the actual file.              
        echo "Compressing Image: $x"
      done
      popd >& /dev/null
    done
    popd >& /dev/null
  fi
done

Sua abordagem parecia bem. Acho que parte do seu problema foi o uso de cd . Você precisa voltar aos níveis de diretório quando estiver "andando" na árvore de diretórios. Normalmente, usarei pushd e popd , como adicionei ao seu exemplo.

Exemplo

Agora, quando eu executo isso no meu diretório de uploads do Wordpress:

$ pwd
/var/www/html/apps/wordpress/wp-content/uploads

Uma amostra de corrida:

$ ./asc.bash | head -15
dir: 2009
found num: 2009
Compressing Image: GURULABS-RPM-GUIDE-v1.0.pdf
Compressing Image: How_to_create_an_RPM_package.mht
Compressing Image: ss_mtr_1-150x150.png
Compressing Image: ss_mtr_1-300x146.png
Compressing Image: ss_mtr_1.png
Compressing Image: ss_mtr_2-150x150.png
Compressing Image: ss_mtr_2-300x115.png
Compressing Image: ss_mtr_2.png
Compressing Image: ss_mtr_3-150x150.png
Compressing Image: ss_mtr_3-300x117.png
Compressing Image: ss_mtr_3.png
Compressing Image: ss1_trac_gitplugin-1024x262.png
Compressing Image: ss1_trac_gitplugin-150x150.png

Melhorias

Eu adicionaria alguns testes antes de examinar um determinado mês nos casos em que o diretório desse mês estivesse vazio. Caso contrário, você terá isso:

Compressing Image: *
Compressing Image: *
Compressing Image: *

Andar por uma árvore de diretórios como essa pode ser complicado. Como a estrutura de diretórios é bastante estruturada, por que não andar assim:

for dir in 20*/*; do
  echo "$dir"
  for files in $dir/*; do
    if [ -e $dir/$files ]; then
      echo "$dir/$files: ..compress.."
    fi
  done
done

Ou assim:

for year in $(printf '%4d\n' {2000..2014}); do
  echo "$year"
  for mnth in $(printf '%02d\n' {00..12}); do
    if [ -e $year/$mnth ]; then
      echo "$mnth"
    fi
  done
done
    
por 14.04.2014 / 14:16