5

I am working on a bash script to compress the images in my Wordpress folders. The wordpress folder structure is as follows:

> 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 

In the uploads folder I have a number of other folders (which were created when plugins were installed), so I'm trying to loop through the folders with numeric names only and then compress the images. Here is what I have so far:

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 

I'm trying to use reg ex to detect the numeric folders, this isn't quite right, but I think I'm close.

4
  • Yes, I could do that for the months alright.
    – Stephen
    CommentedApr 14, 2014 at 9:43
  • @bdowning Where do you live that has 13 months?CommentedApr 14, 2014 at 21:46
  • force of habit to use zero offset, oops. IIRC the Zorastrian calendar does have 13 months. :)
    – bsd
    CommentedApr 15, 2014 at 10:48
  • The months don't change, why not loop over the actual values? 2nd level: for mon in {01..12}; do ...
    – bsd
    CommentedApr 15, 2014 at 10:48

2 Answers 2

5

You can use bash extended globbing for this:

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 

From the man page:

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

So putting a number range inside will match files/directories. Adding the && conditional will ensure that you only compress images if the match is a directory (and that you actually succeeded in entering it).

Without the extended globbing, you could even just do [1-2][0-9][0-9][0-9]/[0-1][0-9]. This is better than trying a brace expansion as you won't end up attempting to enter directories for every single year/month, even if you have no images from then.

5
  • I'm getting the following errors:
    – Stephen
    CommentedApr 14, 2014 at 10:28
  • @Stephen, I am not seeing your errors. Please add them to your question instead of posting them in comments.
    – Graeme
    CommentedApr 14, 2014 at 10:30
  • The error will probably be because you don't cd back from the subdirectory you moved into so the next loops will fail.
    – terdon
    CommentedApr 14, 2014 at 14:11
  • Sorry Graeme, I got sidetracked for a few hours. Terdon is correct that was the error I was getting, resolved now.
    – Stephen
    CommentedApr 14, 2014 at 15:40
  • @Stephen, updated. You can fix this by adding the PWD to the glob.
    – Graeme
    CommentedApr 14, 2014 at 18:50
2

I think I would've done this using find but just to help answer your scripting questions I've modified your example slightly.

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

Your approach seemed fine. I think part of your issue was the use of cd. You need to go back directory levels as you're "walking" the directory tree. I'll typically use pushd and popd instead, as I've added these to your example.

Example

Now when I run this on my Wordpress uploads directory:

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

A sample run:

$ ./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 

Improvements

I'd add some tests prior to looking through a given month in cases where that month's directory is empty. Otherwise you'll get this:

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

Walking a directory tree like this can be tricky. Since the directory structure is fairly structured, why not walk it like this:

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

Or like this:

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 

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.