Shell 在循环中将文件名与字符串进行比较的脚本问题

Shell Script issue with comparing file name to string in a loop

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

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

我会重写脚本。

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

您应该在每个循环中只调用一次 ls | head -n 1。检查后您再次调用 ls | head -n 1,结果可能不同(并发 process.sh 仍然 运行 或新文件)。
你想如何在 file.txt 之后列出文件?您正在跳出循环,其他文件将被跳过。不要在继续中更改它,因为你将继续分配 file.txtfilename.
始终为您的变量使用双引号(想想 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 "%"'