Bash Shell循环遍历文件

时间:2020-01-09 10:37:24  来源:igfitidea点击:

如何对当前目录或指定目录中存储的文件运行shell循环?
您可以使用通配符在bash或任何其他UNIX shell下的一组shell文件上轻松使用for循环。

语法

通用语法如下:

for f in file1 file2 file3 file5
do
echo "Processing $f"
# do something on $f
done

您还可以使用shell变量:

FILES="file1
/path/to/file2
/etc/resolv.conf"
for f in $FILES
do
	echo "Processing $f"
done

您可以循环浏览所有文件,例如* .c,输入:

$ for f in *.c; do echo "Processing $f file.."; done

示例Shell脚本循环遍历所有文件

#!/bin/bash
FILES=/path/to/*
for f in $FILES
do
  echo "Processing $f file..."
  # take action on each file. $f store current file name
  cat $f
done

文件名扩展

您可以循环进行文件名扩展,例如对当前目录中的所有pdf文件进行处理:

for f in *.pdf
do
	echo "Removing password for pdf file - $f"
done

但是,上述语法存在一个问题。
如果当前目录中没有pdf文件,它将扩展为* .pdf(即f将设置为* .pdf)。
为避免此问题,请在for循环之前添加以下语句:

#!/bin/bash
# Usage: remove all utility bills pdf file password 
shopt -s nullglob
for f in *.pdf
do
	echo "Removing password for pdf file - $f"
        pdftk "$f" output "output.$f" user_pw "YOURPASSWORD-HERE"
done

使用Shell变量和While循环

您可以从文本文件中读取文件列表。
例如,创建一个名为/tmp/data.txt的文本文件,如下所示:

file1
file2
file3

现在,您可以按以下方式使用while循环来逐一读取和处理每个循环:

#!/bin/bash
        while IFS= read -r file
        do
                [ -f "$file" ] && rm -f "$file"
        done < "/tmp/data.txt"

这是另一个示例,它从chroot的lighttpd/nginx或Apache Web服务器中删除所有不需要的文件:

#!/bin/bash
_LIGHTTPD_ETC_DEL_CHROOT_FILES="/usr/local/theitroad/conf/apache/secure/db/dir.etc.list"
secureEtcDir(){
        local d=""
        local _d="/jails/apache/$d/etc"
        local __d=""
        [ -f "$_LIGHTTPD_ETC_DEL_CHROOT_FILES" ] || { echo "Warning: $_LIGHTTPD_ETC_DEL_CHROOT_FILES file not found. Cannot secure files in jail etc directory."; return; }
        echo "* Cleaning etc FILES at: \"$_d\" ..."
        while IFS= read -r file
        do
                __d="$_d/$file"
                [ -f "$__d" ] && rm -f "$__d"
        done < "$_LIGHTTPD_ETC_DEL_CHROOT_FILES"
}
 
secureEtcDir "theitroad.com"

处理命令行参数

#!/bin/bash
# make sure you always put $f in double quotes to avoid any nasty surprises i.e. "$f"
for f in $*
do
  echo "Processing $f file..."
  # rm "$f"
done

或者

#!/bin/bash
# make sure you always put $f in double quotes to avoid any nasty surprises i.e. "$f"
for f in $@
do
  echo "Processing $f file..."
  # rm "$f"
done

请注意,$@扩展为$1 $2 $3 $n,而$*扩展为$1y $2y $3y $n,其中y是IFS变量的值,即$*是一个长字符串,$IFS充当分隔符或令牌定界符。
以下示例使用shell程序变量存储实际路径名,然后使用for循环处理文件:

#!/bin/bash
_base="/jail/.conf"
_dfiles="${base}/nginx/etc/conf/*.conf"
 
for f in $_dfiles
do
        lb2file="/tmp/${f##*/}.$$"   #tmp file
        sed 's/Load_Balancer-1/Load_Balancer-2/' "$f" > "${lb2file}"   # update signature 
        scp "${lb2file}" [email protected]:${f}   # scp updated file to lb2
        rm -f "${lb2file}"
done