【问题标题】:Can i do one loop instead of two?我可以做一个循环而不是两个循环吗?
【发布时间】:2020-10-01 19:45:26
【问题描述】:

我在 ${MY_DIR} 有一个文件列表。

ABC_foo123.txt
ABC_foo456.txt
ABC_bar100.txt

需要对这些文件做一些操作。

我的代码:

#!/usr/bin/ksh

ls -l ${MY_DIR}/ABC_foo*.txt
RV=$?
if [[ $RV -eq 0 ]];then
        echo "files found for processing"
        for sFile in `ls -1 ${MY_DIR}/ABC_foo*.txt`
do
        fileNameOnly=$(basename ${sFile})
        echo processing $sFile
        #Doing some operations here
done
else
    echo "No foo files found to process"
fi

ls -l ${MY_DIR}/ABC_bar*.txt
RV=$?
if [[ $RV -eq 0 ]];then
        echo "files found for processing"
        for sFile in `ls -1 ${MY_DIR}/ABC_bar*.txt`
do
        fileNameOnly=$(basename ${sFile})
        echo processing $sFile
        #Doing some operations here
done
else
    echo "No bar files found to process"
fi

这是按预期进行的。但是,有没有一种方法可以使用一个循环而不是两个循环。我觉得我在做同样的事情两次。 欢迎任何建议

【问题讨论】:

  • 我认为ls -1 ${MY_DIR}/ABC_bar*.txt 应该是ls -1 ${MY_DIR}/ABC_bar*.sql

标签: shell for-loop unix ksh


【解决方案1】:

不确定ksh,但在bash 你可以这样做:

for sFile in ABC_{foo,bar}*.txt; do 

在通用外壳中,您可以简单地这样做:

for sFile in ABC_foo*.txt ABC_bar*.txt; do 

要检查是否已处理任何文件,执行以下操作可能更简洁:

flag=0
for sFile in "${MY_DIR}"/ABC_foo*.txt "${MY_DIR}"/ABC_bar*.txt; do
    flag=1
    # process sFile
done
if test "$flag" = 0; then echo "error" >&2; done

使用 glob 可以防止过滤ls 的输出时出现的许多错误,但可能会在非常大的目录中遇到问题(例如,具有数十万条目的目录)。如果这是一个问题,您可能想查看find 的变体。

【讨论】:

  • 让我试试这个
【解决方案2】:

如果您没有对每种类型进行相同的处理:

#!/bin/ksh

MY_DIR=$1

nbr_txt=0
nbr_sql=0

for file in $MY_DIR/*.txt $MY_DIR/*.sql; do
    case ${file##*/} in
        *.txt) ((nbr_txt++))
                # Processing txt type files
                ;;
        *.sql) ((nbr_sql++))
                # Processing sql type files
                ;;
    esac
done

print "$nbr_txt txt files processed"
print "$nbr_sql sql files processed"

根据 cmets 编辑

【讨论】:

  • 嗯,这是“bar”文件与 .sql 的唯一位置....假设这是一个错字。但是,这并不重要,只需使用适当的测试来制作 case 语句...我将使用 .sql 和 .txt 之间的差异进行编辑。
【解决方案3】:

如果您在不同的地方有类似的代码,请考虑使用函数。
类似的东西

#!/usr/bin/ksh

operate_file() {
   filebase="$1"
   extenstion="$2"
   ls -l ${MY_DIR}/${filebase}*.${extension}
   RV=$?
   if [[ $RV -eq 0 ]]; then
      echo "files found for processing"
      for sFile in ${MY_DIR}/${filebase}*.${extension}; do
         fileNameOnly=$(basename ${sFile})
         echo "processing $sFile"
         #Doing some operations here
      done
   else
     echo "No foo files found to process"
   fi
}

operate_file ABC_foo txt
operate_file ABC_bar sql

【讨论】:

    猜你喜欢
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    相关资源
    最近更新 更多