if 语句判断文件是否在目录中

if 语句判断文件是否在目录中

我正在编写一个 bash 脚本,希望它告诉我目录中的文件名是否出现在文本文件中,如果没有,则删除它们。

像这样的东西:

counter = 1
numFiles = ls -1 TestDir/ | wc -l 
while [$counter -lt $numFiles]
do
     if [file in TestDir/ not in fileNames.txt]
     then
          rm file
     fi
     ((counter++))
done

答案1

不要将文件列表保存在变量中,而是循环名称:

for name in TestDir/*; do
    # the rest of the code
done

要测试是否$name出现在 中fileNames.txt,请使用grep -q

for name in TestDir/*; do
    if ! grep -qxF "$name" fileNames.txt; then
        echo rm "$name"
    fi
done

makes执行字符串比较,而不是正则表达式匹配。使用 时,我们-F没有得到任何输出,只有一个可以与语句一起使用的退出状态(如果找到字符串,则为 true,但感叹号会反转测试的含义)。 表示字符串需要匹配整行,从头到尾,而不仅仅是一行的一部分。grep-qgrepif-xgrep$name

rm我已经用保护了实际echo。运行并确保删除正确的文件。

如果列出的文件名没有TestDir路径,则将$name命令更改grep${name##*/}

for name in TestDir/*; do
    if ! grep -qxF "${name##*/}" fileNames.txt; then
        echo rm "$name"
    fi
done

这将查找路径的文件名部分$name而不是完整路径,包括TestDir.

答案2

zsh

expected=(${(f)"$(<fileNames.txt)"}) || exit
cd TestDir || exit
actual=(*(D))
superfluous=(${actual:|expected})
if (($#superfluous)) {
  echo These files are not in the expected list:
  printf ' - %q\n' $superfluous
  read -q '?Do you want to delete them? ' && rm -rf -- $superfluous
}

答案3

这是使用您的方法的工作版本:

#!/bin/bash
fileList="$1"
targetDir="$2"

## Read the list of files into an associative array
declare -A filesInFile
while IFS= read -r file; do
  filesInFile["$file"]=1
done < "$fileList"

## Collect the files in the target dir
filesInDir=("$targetDir"/*);

for file in "${filesInDir[@]}"; do
  file=${file##*/}; # get the name of the file; remove path
  ## If this file has no entry in the array, delete
  if [[ -z "${filesInFile[$file]}" ]]; then
      echo "rm $file"
  fi
done

删除echo即可实际删除文件。请注意,我没有检查文件数量是否不同,因为考虑到文件数量可能相同,但您仍然可能拥有名称不在列表中的文件,这似乎没有多大意义。

相关内容