【问题标题】:Shell Script While Loop and Perl Printing Extra LineShell 脚本 While 循环和 Perl 打印额外行
【发布时间】:2017-04-27 22:01:52
【问题描述】:

我修改了海报从另一个板上给我的脚本,以更好地满足我的需要。 InputConfig.txt 包含在其中查找文件的目录、入站文件期限(第二列)和出站文件期限(第三列)。每个目录的这些入站/出站号码不必相同,我只是这样做了。最重要的是 VI 和 AB 目录有特定的年龄要检查,其他一切都使用通用的 30 分钟。

Perl 语句的目的是捕获找到的每个文件的时间戳。问题是 printf 加了一行,因为 while 循环正在读取 3 行,但我只需要打印 2 行(或多行)。

我不太了解 Perl,无法修复它 - 如果问题出在 Perl 上的话。

感谢您的帮助。

InputConfig.txt

/home/MF/NA/CD 30 30
/home/MF/NA/CD/VI 10 10
/home/MF/NA/CD/AB 15 15

脚本

#!/bin/ksh

VI=*/CD/VI/*
AB=*/CD/AB/*

cat InputConfig.txt | while read DIR IT OT; do
TS=$(find "${DIR}" -type f -path "${DIR}/*/inbound/*" -mmin "+${IT}" ! -path "${VI}" ! -path "${AB}")
TS=$(find "${DIR}" -type f -path "${DIR}/*/outbound/*.done" -mmin "+${OT}")
TS=$(find "${DIR}" -type f -path "${DIR}/inbound/*" -mmin +"${IT}")
perl -e 'printf("%s,%d\n", $ARGV[0], (stat("$ARGV[0]"))[9]);' "$TS" 
done

输出:

,0
/home/MF/NA/CD/VI/inbound/vis,1492716168
/home/MF/NA/CD/AB/inbound/abc,1492716485

期望的输出

/home/MF/NA/CD/VI/inbound/vis,1492716168
/home/MF/NA/CD/AB/inbound/abc,1492716485

【问题讨论】:

  • 在您的循环的第一次迭代中,$TS 似乎是空的?所以perl -e 的输出是",0"...另外,当InputConfig.txt 有3 行时,为什么你期望有两行输出
  • 你有三行输入,你要求perl为每一个打印一行...你只是缺少if length($ARGV[0])吗?
  • @HåkonHægland 我希望有 2 行输出,因为这些是“查找”找到的文件。第一行与我无关。
  • @ikegami 我希望 Perl 仅打印找到的文件的行。我知道它会因为输入而打印 3 行,但有没有办法让它只打印 find 命令返回的内容?
  • 简直不懂。这是一行中的 3x 分配 TS=$(..),因此将使用唯一的最后一个。前两个发现有什么意义?

标签: perl shell loops while-loop


【解决方案1】:

脚本有很多问题:

  • 它在TS 变量的行中分配了3x,因此,只有最后一个将被使用。 find 的前两次运行毫无意义 - 所以您可能想要实现其他目标。
  • 您正在使用perl 获得mtime。如果您从stdin 读取文件名而不是启动perl X 次,这是一个很酷的主意。在这种情况下,使用stat shell 命令会更快——换句话说,您想从stdin 中读取文件名。
  • 总是使用read -r(除非你知道为什么不想要-r):)
  • cat 的无用使用。只需从文件重定向整个循环输入

所以,脚本可能看起来像:

#!/bin/ksh

VI=*/CD/VI/*
AB=*/CD/AB/*

while read -r DIR IT OT; do
    find "${DIR}" -type f -path "${DIR}/*/inbound/*" -mmin "+${IT}" ! -path "${VI}" ! -path "${AB}" -print
    find "${DIR}" -type f -path "${DIR}/*/outbound/*.done" -mmin "+${OT}" -print
    find "${DIR}" -type f -path "${DIR}/inbound/*" -mmin +"${IT}" -print
done < InputConfig.txt | perl -lne 'printf "%s,%d\n", $_, (stat($_))[9];'

这是ksh 和/或shell 问题perl。 :)

【讨论】:

    【解决方案2】:

    如果我很好理解的话,你想使用 perl 来显示之前的 find 命令找到的文件的名称和大小。类似的东西应该可以工作:

    #!/bin/ksh
    
    VI=*/CD/VI/*
    AB=*/CD/AB/*
    
    cat InputConfig.txt | while read DIR IT OT; do
    (find "${DIR}" -type f -path "${DIR}/*/inbound/*" -mmin "+${IT}" ! -path "${VI}" ! -path "${AB}" ;
    find "${DIR}" -type f -path "${DIR}/*/outbound/*.done" -mmin "+${OT}" ;
    find "${DIR}" -type f -path "${DIR}/inbound/*" -mmin +"${IT}") |
    xargs -l perl -e 'printf("%s,%d\n", $ARGV[0], (stat("$ARGV[0]"))[9]);'
    done
    

    【讨论】:

      【解决方案3】:

      感谢大家的输入,但我回到了我原来的 if-else 脚本方法,因为我从中调用脚本的 TIBCO 项目不喜欢输出格式。

      我的脚本,像 ./CDFindFiles /home/NA/CD/ 一样调用:

      #!/bin/ksh
      
      FOLDER=$1
      VI=*/CD/VI/inbound
      AB=*/CD/AB/inbound
      
      find "$FOLDER" -type f -path "${FOLDER}*/inbound/*" -o -path "${FOLDER}*/outbound/*.done" | while read line;
       do
        MODTIME=$(perl -e 'printf "%d\n",(-M shift)*24*60' "$line")
        if [[ "$line" == *"$VI"* && "$MODTIME" -gt 90 || "$line" == *"$AB"* && "$MODTIME" -gt 180 ]]; then
         perl -e 'printf("%s,%d\n", $ARGV[0], (stat("$ARGV[0]"))[9]);' "$line"
        elif [[ "$line" != *"$VI"* && "$line" != *"$AB"* &&  "$MODTIME" -gt 30 ]]; then
          perl -e 'printf("%s,%d\n", $ARGV[0], (stat("$ARGV[0]"))[9]);' "$line"
         fi
       done
      

      【讨论】:

        猜你喜欢
        • 2016-08-06
        • 2017-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-06
        • 2017-09-20
        相关资源
        最近更新 更多