【问题标题】:Shell Script issue with comparing file name to string in a loop在循环中将文件名与字符串进行比较的 Shell 脚本问题
【发布时间】:2017-05-29 17:32:33
【问题描述】:

这就是问题所在。我在 Ubuntu 14.04 服务器上有一个包含超过 100,000K 文件的目录。我需要在后台处理文件,所以我编写了一个 shell 脚本,将文件转换为更大的文件,然后删除文件。然而,发挥作用的问题还在于进程脚本和输出文件。有什么想法吗?

#!/bin/sh
c=0
#loop through 1000 results at 1 time
d=1000 

  while [ $c -lt $d ]
    do
      filename=$(`ls | head -n 1`)
      #echo $filename

  if [ $filename == "process.sh" ]
    then
    break
  fi

  if [ $filename ==  "file.txt" ]
    then
    break
  fi

  cat `ls | head -n 1` >> file.txt
  rm `ls | head -n 1`
  #echo $c
  c=`expr $c + 1`

done

【问题讨论】:

  • 您可以在处理完成后删除违规行:sed -i.bak '/pattern to match/d' ./file.txt
  • 问题是正在处理的文件数量不固定。总是有批量添加的文件。我的意思是有时有 100,000 个,有时更少。我想我可以先从循环中获得文件数,然后从循环中获得-1,因为其他文件都有数字名称。不确定,我想我需要刷一下我对 shell 脚本的了解。
  • 除非我遗漏了什么,ls | head -n 1 将始终返回第一个文件。我没有看到这个脚本在文件中进行。也不应该是filename=$(ls |头 -n 1)filename=$(ls | head -n 1)?在做简单的数学运算时,我更喜欢 c=$((c+1)) 的格式。
  • 不要在循环中调用ls。如果您想处理前 1000 个文件(并且您想要解析 ls),只需执行类似 ls | sed 1000q | while read filename; do ... 的操作
  • 另外,将您的脚本和输出文件放在不同的目录中。

标签: shell ubuntu sh cat rm


【解决方案1】:

您应该在每个循环中只调用一次ls | head -n 1。检查后,您再次调用ls | head -n 1,结果可能会有所不同(并发 process.sh 仍在运行或新文件)。
您想如何获取 file.txt 之后列出的文件?您正在跳出循环,其他文件将被跳过。不要在 continue 中更改此设置,因为您将继续将 file.txt 分配给 filename
始终为你的变量使用双引号(想想my file.txt),你可能也想习惯大括号。

假设您的批处理工作正常,并且已经处理了最后一个非特殊文件。 "${filename}" 将是空的!所以从测试if [ -f "${filename}" ]开始,这样也能解决目录问题。

我真的希望你有删除这些文件的权限,这样你就不会因为处理同一个文件 1000 次而陷入困境。

你不应该处理 ls 输出,所以替代

ls | egrep -v "file.txt|process.sh" | head -n 1

只是做错的另一种方式。

当您收到"${filename}" 并想根据多个字符串检查它时,您可能需要使用case "${filename}" in ... esac

当您的文件没有换行符时,您可以使用 findxargs

# First test it
find . -type f \( ! -name process.sh -a ! -name file.txt \) 2>/dev/null |
   head -10 | xargs -I % sh -c 'echo "File %"; echo "rm -f %"'
# Looking nice?
find . -type f \( ! -name process.sh -a ! -name file.txt \) 2>/dev/null |
   head -1000 | xargs -I % sh -c 'cat "%" > file.txt; rm -f "%"'

【讨论】:

    【解决方案2】:

    我会重写脚本。

    #!/bin/bash
    
    c=0
    d=1000
    
    for file in $(find . -maxdepth 1 -type f \( ! -name process.sh -a ! -name file.txt \))
    do
        cat $file >> file.txt
        rm $file
        c=$((c+1))
        if [ $c -eq $d ]; then
            break
        fi
    done
    

    【讨论】:

      猜你喜欢
      • 2017-01-08
      • 1970-01-01
      • 2016-03-12
      • 2021-03-08
      • 1970-01-01
      • 2013-09-19
      • 1970-01-01
      • 2021-05-22
      • 1970-01-01
      相关资源
      最近更新 更多