用于循环遍历具有数字名称的文件夹的脚本

用于循环遍历具有数字名称的文件夹的脚本

我正在编写一个 bash 脚本来压缩我的 Wordpress 文件夹中的图像。 wordpress文件夹结构如下:

> 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

在上传文件夹中,我有许多其他文件夹(这些文件夹是在安装插件时创建的),因此我尝试仅循环遍历具有数字名称的文件夹,然后压缩图像。这是我到目前为止所拥有的:

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

我正在尝试使用 reg ex 来检测数字文件夹,这不太正确,但我认为我已经接近了。

答案1

您可以bash为此使用扩展通配符:

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

从手册页:

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

因此,在里面放入数字范围将匹配文件/目录。添加&&条件将确保您仅在匹配的是目录时才压缩图像(并且您实际上已成功输入该目录)。

如果没有扩展的通配符,您甚至可以这样做[1-2][0-9][0-9][0-9]/[0-1][0-9]。这比尝试大括号扩展更好,因为您最终不会尝试输入每个年份/月份的目录,即使您那时没有图像。

答案2

我想我会使用以下方法来完成此操作find,但只是为了帮助回答您的脚本问题,我稍微修改了您的示例。

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

你的方法看起来不错。我认为你的问题的一部分是使用cd.当您“遍历”目录树时,您需要返回目录级别。我通常会使用pushdandpopd来代替,因为我已将它们添加到您的示例中。

例子

现在,当我在我的 WordPress 上传目录上运行此命令时:

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

示例运行:

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

改进

在查看给定月份之前,我会添加一些测试,以防该月的目录为空。否则你会得到这个:

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

遍历这样的目录树可能会很棘手。既然目录结构相当结构化,为什么不这样走:

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

或者像这样:

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

相关内容