Find 命令在 for 循环中不起作用

Find 命令在 for 循环中不起作用

我有文件名列表,我想一一提供这些文件来查找命令,以便我可以获得路径。我已经使用 for 循环并使用 cat 命令获取变量中的所有文件名,然后将它们通过变量一一传递给 find 命令,但它不起作用。有人可以指导我吗?

for f in $(cat filelist.txt)
do 
find /home/abc/ -type f -name "$f"
done;

我没有收到任何错误,但也没有得到输出,我也尝试将输出放入变量中,但没有运气。

答案1

如果您想查找名称为每行存储的文件中的任何一个的文件filelist.txt,一种简单的方法是使用zshs globbing

names=( ${(f)"$(<filelist.txt)"} ) &&
  (( $#names )) &&
  print -rC1 -- /home/abc/**/${(~j[|])names}(D.)

至于为什么你的方法不起作用,虽然没有什么问题,但并不是立即显而易见的:

  • 在 中bash,未加引号$(cat filelist.txt)的内容对 的内容调用 split+glob (仅在 zsh 中拆分)filelist.txt。使用默认值$IFS(用于分割部分),它将在换行符上分割,也会在空格和制表符上分割。因此,如果其中有my file.txt一行,它将查找调用的文件my和调用的文件,file.txt而不是调用的文件my file.txt
  • 如果有一个文件*filelist.txt文件,则全局部分会将其扩展为调用脚本的目录中的文件列表。
  • -name '*'不会查找名为 的文件*,但会报告每个文件,因为传递到的内容-name被视为模式。您需要转义[?*with\\禁用通配符运算符。

现在,您的问题也可能是:

  • filelist.txt是 MSDOS 文本格式,带有 CRLF 分隔符而不是 LF。你会运行dos2unix它来修复它。
  • 您有文件路径filelist.txt(例如dir/file.txt)。-name仅匹配文件名,因此永远不会匹配该文件名。

在这里,您可以使用 GNU 代替循环xargs

xargs -rd'\n' -a filelist.txt -I NAME find /home/abc/ -name NAME -type f

但这仍然意味着要抓取每个文件名的整体/home/abc/,这是低效的。

相反,你可以这样做:

xargs -rd'\n' -n200 -a <(sed 's/[*?\\[]/\\&/g' filelist.txt) sh -c '
  for name do
    set -- -o -name "$name"
    shift
  done
  shift
  find /home/abc/ \( "$@" \) -type f' sh

我们find /home/abc/ \( -name name1 -o -name name2... \) -type f在一次调用中调用最多 200 个名称find,这意味着/home/abc.无论如何,不​​如zsh只执行 1 的情况,但仍然好得多。

我们还使用sed转义名称中的通配符。您也可以通过dos2unix那里。

答案2

也试试

find -iname $(sed -z 's/\n$//; s/\n/ -o -iname /g' list.txt)

查找以 *nix 文本文件中不应该存在的字符sed -z结尾的行\000,因此它将整个文件加载到内存中。然后删除尾随<NL>字符,并用剩余字符替换,-o -iname以便find获得一长串ored 文件名。

相关内容