如何从 bash 中的查找文件中“抓取”匹配文件?

如何从 bash 中的查找文件中“抓取”匹配文件?

我有一个包含文件名的查找文件。我还有一个包含文件的目录,其中一些文件的名称与目录中的某些名称相对应。

我怎么能够:

  1. 将完全匹配的文件移动到新目录或
  2. 从现有目录中删除不匹配的文件

另外,如何通过顶级目录及其子目录递归地执行此操作?

答案1

也许是这样的:

sed -e 's;^.*$;\^&\$; list-of-names > list-of-patterns

rm $(find . -type f | grep -v -f list-of-patterns)

请小心,如果文件名包含 shell 认为特殊的空格或字符,这肯定会中断。请在实际运行之前检查一下这会删除什么!

(可能有一种方法可以绕过模式文件,但我根本没有看到它)。

答案2

以下 bash 脚本(警告:未经测试!)将文件从 under 移动/directory/with/the/files到 under /matched/files。仅/path/to/lookup.file移动其名称(无目录)的文件。请注意,如果 中有指向目录的符号链接/directory/with/the/files,则会递归遍历它们,就好像它们本身就是目录一样。

#!/bin/bash
shopt -s globstar
set -f; IFS=$'\n'
typeset -A filenames
for x in $(cat /path/to/lookup.file); do filenames[$x]=1; done
set +f; unset IFS
cd /directory/with/the/files
for x in ./**; do
  if [[ -d "$x/." ]]; then
    : # skip directories and symbolic links to directories
  elif [[ -n ${filenames[${x##*/}]} ]]; then
    # the file is matched, move it under /matched/files
    mkdir -p "/matched/files/${x%/*}"
    mv "$x" "/matched/files/$x"
  else
    # the file isn't matched
    :
  fi
done

说明:

  • shopt -s globstar使**全局递归遍历目录。
  • set -f; IFS=$'\n'关闭通配符并将换行符设置为唯一的单词分隔符,以便$(cat /path/to/lookup/files)仅在换行符处分割未加引号的命令替换。
  • filenames是一个关联数组
  • for x in ./**注意$x始终包含目录部分(这种方式是, with${x%/*}的目录部分,表示顶级目录),并且不以 开头(因此不会有被视为选项的风险)。$x.-
  • ${x##*/}扩展为 的文件名部分$x,即$x没有目录部分。

相关内容